3

I have to let user download a pdf file whene he clock on button, I find that I have to use rn-fetch-blob instead of react-native-fetch-blob. In the documentation there is this code:

const { config, fs } = RNFetchBlob
let DownloadDir = fs.dirs.DownloadDir // this is the Downloads directory.
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : true, //uses the device's native download manager.
notification : true,
title : "Notification Title", // Title of download notification.
path: DownloadDir + "/me_"+ '.' + extension, // this is the path where your download file will be in
description : 'Downloading file.'
}
}
config(options)
.fetch('GET',"https://whatever_url_u _want/)
.then((res) => {
//console.log("Success");
})
.catch((err) => {console.log('error')}) // To execute when download cancelled and other errors
}

I have no idea what I can do with this ! how to use use it in TouchableOpacity onPress prop ? please someone can provide a detailed example

PS. I call an API with POST methode and I receive a link of PDF file. I think

I have to set this link like that
    config(options)
    .fetch('GET',this.state.data.link)

3 Answers 3

19
  1. Add below permissions in AndroidManifest.xml
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" />
  1. To use downloadmanager, add below action in intent in AndroidManifest.xml
<intent-filter>
     <action android:name="android.intent.action.MAIN" />
     <category android:name="android.intent.category.LAUNCHER" />
     <action android:name="android.intent.action.DOWNLOAD_COMPLETE"/>                          
</intent-filter>
  1. import PermissionsAndroid, Alert from react native (android only)
import {PermissionsAndroid, Alert} from "react-native";
  1. Now in component
actualDownload = () => {
   const { dirs } = RNFetchBlob.fs;
  RNFetchBlob.config({
    fileCache: true,
    addAndroidDownloads: {
    useDownloadManager: true,
    notification: true,
    mediaScannable: true,
    title: `test.pdf`,
    path: `${dirs.DownloadDir}/test.pdf`,
    },
  })
    .fetch('GET', 'http://www.africau.edu/images/default/sample.pdf', {})
    .then((res) => {
      console.log('The file saved to ', res.path());
    })
    .catch((e) => {
      console.log(e)
    });
}

downloadFile = () => {
  try {
      const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        this.actualDownload();
      } else {
        Alert.alert('Permission Denied!', 'You need to give storage permission to download the file');
      }
    } catch (err) {
      console.warn(err);
    } 
}

render(){
  <TouchableOpacity onPress={this.downloadFile}>
    <Text>Download!!!</Text>
  </TouchableOpacity>
}

CAUTION: You need to ask for storage permission for android 6 or higher in runtime

Sign up to request clarification or add additional context in comments.

12 Comments

thanks for your response but I tried your code without any modification but when I run my application I have an error : unsupported path /data/data/com.nameOfMyApp/files/test.pdf - this is the error, I'm a real beginner so can you help more ?
I have updated my answer, try to save in DownloanDir not DocumentDir ${dirs.DownloadDir}/test.pdf
I tried this too I have a notification: Download unsuccesful. ans when I console.warn the error I have that: Download manager failerd to download from http.... Statut code = 16
same thing with your code , it gave me an error when I console.warn it: line:160418, column: 34, sourceURL: 10.0.2.2:8081/…
It's okey when I generate an APK it works fine on mobile I have just have set somthing to open file directly when I click on notification of downloading
|
11

LATEST WORKING SOLN both ios/android

Follow mosabbir tuhin's answer and then use my function actualDownload() and permissionFunc() to make pdf work on ios also.

const permissionFunc = async () => {
    if (Platform.OS == 'ios') {
        actualDownload();
    } else {
        if (downloaded) {
            try {
                const granted = await PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
                if (granted === PermissionsAndroid.RESULTS.GRANTED) {
                    actualDownload();
                } else {
                    showSnackbar('You need to give storage permission to download the file');
                }
            } catch (err) {
                console.warn(err);
            }
        }
        else {
            showSnackbar('File is already downloaded.');
        }
    }
}

const actualDownload = () => {
    const { dirs } = RNFetchBlob.fs;
    const dirToSave = Platform.OS == 'ios' ? dirs.DocumentDir : dirs.DownloadDir
    const configfb = {
        useDownloadManager: true,
        notification: true,
        mediaScannable: true,
        title: pdfInfo.pdf,
        path: `${dirToSave}/${pdfInfo.pdf}`,
    }
    const configOptions = Platform.select({
        ios: {
            title: configfb.title,
            path: configfb.path,
            appendExt: 'pdf',
        },
        android: configfb,
    });

    console.log('The file saved to 23233', configfb, dirs);

    RNFetchBlob.config(configOptions)
        .fetch('GET', `https://aquatherm.s3.ap-south-1.amazonaws.com/pdfs/${pdfInfo.pdf}`, {})
        .then((res) => {
            if (Platform.OS === "ios") {
                RNFetchBlob.ios.previewDocument(configfb.path);
            }
            setisdownloaded(false)
            if (Platform.OS == 'android') {
                showSnackbar('File downloaded');
            }
            console.log('The file saved to ', res);
        })
        .catch((e) => {
            setisdownloaded(true)
            showSnackbar(e.message);
            console.log('The file saved to ERROR', e.message)
        });
}

1 Comment

As we are already giving absolute path to save the file we shouldn't give fileCache property in the configOptions for ios.Also we can remove this line RNFetchBlob.fs.writeFile(configfb.path, res.data, 'base64');
0

here's a fully working download handler inspired from Ajmal's answer, also fixed the issue i faced while downloading on android using his code:

export const handleDownload = async ({url, fileName}) => {
  try {
    const isGranted = await requestStoragePermission();
    if (!isGranted) {
      showToast({
        type: 'error',
        title: 'error',
        subTitle:
          'required permissions not granted. please enable the recording permission from settings',
      });
      return;
    }

    const {config, fs} = RNFetchBlob;

    const dirToSave = isIos ? fs.dirs.DocumentDir : fs.dirs.DownloadDir;
    const configfb = {
      addAndroidDownloads: {
        useDownloadManager: true,
        notification: true,
        mediaScannable: true,
        title: fileName,
        path: `${dirToSave}/${fileName}`,
      },
    };

    const configOptions = Platform.select({
      ios: {
        title: fileName,
        path: `${dirToSave}/${fileName}`,
      },
      android: configfb,
    });
    config(configOptions)
      .fetch('GET', url)
      .then(res => {
        if (isIos) {
          RNFetchBlob.ios.previewDocument(res?.path());
        } else {
          showToast({
            type: 'success',
            title: 'success',
            subTitle: 'file downloaded successfully',
          });
        }
      })
      .catch(error => {
        showToast({
          type: 'error',
          title: 'error',
          subTitle: 'failed to download file',
        });
      });
  } catch (error) {
    showToast({
      type: 'error',
      title: 'error',
      subTitle: 'failed to download file',
    });
  }
};

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.