rn-fetch-blob icon indicating copy to clipboard operation
rn-fetch-blob copied to clipboard

Download issue: `than` callback succeeds with status 200 when device goes offline

Open olegmilan opened this issue 5 years ago • 3 comments

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:

Broken image 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

olegmilan avatar Oct 14 '19 17:10 olegmilan

Was this issue fixed> I'm facing same problem?

AppcDevSon avatar Oct 05 '20 18:10 AppcDevSon

Was this issue fixed> I'm facing same problem?

panktiszluck avatar May 10 '22 07:05 panktiszluck

I don't know @AppcDevSon @panktiszluck, but I'm still using this workaround

olegmilan avatar Jan 15 '24 12:01 olegmilan