rn-fetch-blob
rn-fetch-blob copied to clipboard
Download issue: `than` callback succeeds with status 200 when device goes offline
Overview:
There's an issue with download images.
When I turn off wifi/4g during download images .then
callbacks with 200 status are being called.
This causes issues when some of the images are partially loaded.
This not only Android related. I have similar issues on IOS as well
Libraries:
"react-native": 0.60.4
"rn-fetch-blob": "^0.11.2", (also tested with 0.10.16)
Issue sample:
Code sample:
downloadImage(image) {
const { url, systemFilePath, headers } = image;
RNFetchBlob
.config({
fileCache: true,
path: systemFilePath,
})
.fetch('GET', url, headers)
.then((res) => {
// Run success callback only if 200 status was received
// Otherwise treat this as an error
const status = res.info().status;
if (status === 200) {
log('Image was loaded successfully', url, systemFilePath, res);
this.onImageLoaded(image);
} else {
// Clear broken image
res.flush();
this.onImageLoadError(image, status, `Status code: ${status}`);
}
})
.catch((err) => {
this.onImageLoadError(image, null, err);
});
}
In order to overcome this issue I had to create mechanism by comparing downloaded image size with Content-length from headers(downloadImage
and checkDownloadedImage
):
Temporary solution:
// Check download image response
// + check downloaded image size, to be sure that we loaded whole file
checkDownloadedImage = (response, filePath) => {
return new Promise((resolve, reject) => {
const info = response.info();
const status = _.get(info, 'status');
// If status if wrong, reject promise
if (status !== 200) {
return reject(`Status code: ${status}`);
}
const contentLengthStr = _.get(info, 'headers.Content-Length', '');
const contentLength = contentLengthStr && parseInt(contentLengthStr);
// If server does not provide file size, we cannot detect if file was fully loaded
// so resolve promise
if (!contentLength) {
return resolve();
}
// Check if downloaded image has equal size with Headers Content-Length
return RNFetchBlob.fs.stat(filePath)
.then((stat) => {
// If downloaded image size is less than Content Length, clear file and throw an error
if (stat.size < contentLength) {
return reject('Error! Downloaded image size is less than size on server');
}
resolve();
})
.catch((err) => reject(err));
});
};
downloadImage(image) {
log('downloadImage request', image);
const { url, systemFilePath, headers } = image;
RNFetchBlob
.config({
fileCache: true,
path: systemFilePath,
})
.fetch('GET', url, headers)
.then((res) => {
// TODO remove in future if rn-fetch-blob will fix those issues on Android and IOS
// hack to identify broken image if callback is successful
return this.checkDownloadedImage(res, systemFilePath)
.then(() => this.onImageLoaded(image))
.catch((error) => {
// Clear broken image and run error callback
res.flush();
this.onImageLoadError(image, status, error);
});
})
.catch((err) => {
this.onImageLoadError(image, null, err);
});
}
Thank you guys. You are doing a great job. Hopefully this one will be fixed
Similar/related issues:
https://github.com/joltup/rn-fetch-blob/issues/311 https://github.com/joltup/rn-fetch-blob/issues/336
Related PR's
https://github.com/joltup/rn-fetch-blob/pull/449
Was this issue fixed> I'm facing same problem?
Was this issue fixed> I'm facing same problem?
I don't know @AppcDevSon @panktiszluck, but I'm still using this workaround