C1rcu1tB04rd
C1rcu1tB04rd

Reputation: 126

Downloading image file with react native fetch blob

I am trying to learn react native and how to download files to the device. I know you can do this with react native file system but that does not support authentication which I need. React native fetch blob does support this.

For education purposes, I want to have the code from the first answer to this question recreated in react native fetch blob instead of react native file system.

I someone could write sutch an examlple form me I would be super tankfull.

Question: Downloading data files with React Native for offline use

Upvotes: 0

Views: 8085

Answers (3)

gaurav rana
gaurav rana

Reputation: 1

Inject JS to handle the blob file download(injected JS should be wrapped inside ``).

const injectedJS = `(function() {
    window.ReactNativeWebView.postMessage = function(data) {
      window.ReactNativeWebView.postMessage(JSON.stringify(data));
    };
    document.addEventListener('click', function(e) {
      const element = e.target;
       const anchor = document.querySelector('a[href^="blob:"]');
    if (anchor && anchor.getAttribute('href')) {
        e.preventDefault();
        const xhr = new XMLHttpRequest();
        let href = anchor.getAttribute('href')
        const fileName = anchor.getAttribute('download') || 'downloaded-file';
         fetch(href)
          .then(response => response.blob())
          .then(blob => {
            const reader = new FileReader();
            reader.readAsDataURL(blob);
            reader.onloadend = function() {
              const base64Data = reader.result.split(',')[1];
              window.ReactNativeWebView.postMessage(JSON.stringify({
                base64Data: base64Data,
                fileName: fileName
              }));
            };
          })
          .catch(error => {
            console.error('Failed to fetch blob data:', error);
          });
    } else {
      console.log('href not loaded yet.');
    } 
    });
  })()`;

  const handleMessage = async event => {
    try {
      const { base64Data, fileName } = JSON.parse(event.nativeEvent.data);
      if (!base64Data) {
        throw new Error('Base64 data is undefined');
      }
      const filePath = `${RNBlobUtil.fs.dirs.DownloadDir}/${fileName}`;
      // Save the Base64 data as a file
      await RNBlobUtil.fs.writeFile(filePath, base64Data, 'base64');
      // Trigger a download intent on Android
      await RNBlobUtil.android.actionViewIntent(filePath, 'application/pdf');
    } catch (error) {
      console.error('File download error:', error);
    }
  };

<WebView
      source={{
        uri
      }}
      allowsBackForwardNavigationGestures
      bounces
      cacheEnabled={false}
      contentMode="mobile"
      domStorageEnabled={true}
      geolocationEnabled
      incognito
      javaScriptCanOpenWindowsAutomatically
      javaScriptEnabled={true}
      mixedContentMode="compatibility"
      originWhitelist={['https:*', 'blob:*']}
      ref={webViewRef}
      scalesPageToFit
      sharedCookiesEnabled
      startInLoadingState={true}
      style={styles.container}
      thirdPartyCookiesEnabled
      onLoadEnd={() => {
        webViewRef.current?.injectJavaScript(injectedJS);
      }}
      onMessage={handleMessage}
    />

Upvotes: 0

S Debasish Nayak
S Debasish Nayak

Reputation: 263

downloadImage(){
   var date      = new Date();
   var url       = "http://debasish.com/image.jpg";
   var ext       = this.getExtention(url);
   ext = "."+ext[0];
   const { config, fs } = RNFetchBlob ; 
   let PictureDir = fs.dirs.PictureDir
   let options = {
   fileCache: true,
    addAndroidDownloads : {
      useDownloadManager : true,
      notification : true,
      path:  PictureDir + "/image_"+Math.floor(date.getTime() 
          + date.getSeconds() / 2)+ext,
     description : 'Image'
      }
   }
    config(options).fetch('GET', url).then((res) => {
      Alert.alert("Download Success !");
   });
}
  getExtention(filename){
    return (/[.]/.exec(filename)) ? /[^.]+$/.exec(filename) : 
undefined;

}

Upvotes: 1

Ho&#224;ng Vũ Anh
Ho&#224;ng Vũ Anh

Reputation: 677

Try this, it's work fine on Android:

export const download = (url, name) => {
  const { config, fs } = RNFetchBlob;
  let PictureDir = fs.dirs.PictureDir;
  let options = {
    fileCache: true,
    addAndroidDownloads: {
      useDownloadManager: true,
      notification: true,
      path: PictureDir + name,
      description: t('downloading_file')
    }
  };
  config(options)
    .fetch('GET', url)
    .then(res => {
      if (res.data) {
        alert(t('download_success'));
      } else {
        alert(t('download_failed'));
      }
    });
};

Upvotes: 1

Related Questions