Node JS/Gzip: Image file download ends prematurely with no error
I would recommend you trying to check that the writeStream
's bytesWritten
property equals to the content-length
header you are receiving.
I have been playing around with your code and I have found that the end
event for the request gets fired before the writeStream
is closed, so I think there is actually no way for you to check this property at this point. Instead you should validate it on the close
event of your writeStream
.
Try this sample code and tell us how it goes:
const fs = require('fs-extra');
const request = require('request');
var probe = require('probe-image-size');
var progress = require('request-progress');
var filename = 'C:/Users/User/Desktop/myimage.jpg';
var writeSteam = fs.createWriteStream(filename)
var req = request(createRequestHeaders('www.linktomyimage.com/image.jpg'));
downloadImage(req, filename)
function createRequestHeaders(url) {
var cookie = `userid=${userid}; phash=${phash};`;
return {
'url': url,
'method': 'GET',
'gzip': true,
'headers': {
'Referer': `https://${website}/`,
'Cookie': cookie
}
};
}
function downloadImage(req, filename) {
return new Promise((resolve, reject) => {
var response = null;
var bytes;
var dirname = path.dirname(filename);
if (!fs.existsSync(dirname)) fs.ensureDirSync(dirname);
// NEW CODE
writeSteam.on('close', () => {
if (bytes !== writeSteam.bytesWritten) { // NEW CODE
// Here the write stream is closed, so we can compare the property bytesWritten with the bytes we expected to receive
console.log('The size is not equal! Image is corrupt!')
reject({ 'name': 'ImageCorrupt'})
} else if (response.statusCode === 200) {
var input = require('fs').createReadStream(filename);
probe(input).then(result => {
input.destroy();
if (result != null) {
resolve({bytes: bytes, width: result.width,
height: result.height,});
} else {
// The image size probe does not detect if the download was truncated
reject({ 'name': 'ImageMissingOrCorrupt'});
}
}).catch((error) => {
reject(error);
});
} else {
// This is never triggered when the download stops and the image is truncated
reject({ 'name': 'StatusCodeError', 'message': response.statusCode });
}
})
progress(req, { delay: 0 }).on('progress', function (state) {
updateDownloadSpeed(state.speed);
}).on('end', function () {
console.log('Ended request!!') // NEW CODE
}).on('response', function (resp) {
response = resp;
bytes = response.headers['content-length'];
}).on('error', function (error) {
// This does not detect when an image is truncated either
reject(error);
}).pipe(writeSteam);
});
}