joltup / rn-fetch-blob

A project committed to making file access and data transfer easier, efficient for React Native developers.
MIT License
2.81k stars 772 forks source link

Bad base64 - Android only issue #667

Open niall-cooley opened 3 years ago

niall-cooley commented 3 years ago

I am having an issue within react native where I am downloading a base 64 string from an API and rendering it as a PDF on mobile devices.

The project is built with React native - the code works fine on iOS but on Android we are getting a 'bad base 64' / invalid PDF format error.

I am running v0.12.0 of rn-fetch-blob.

Step One: On button click

getBill = () => {
    if (Platform.OS === "android") {
      this.getAndroidPermission();
    } else {
      this.downloadBill();
    }
  };

Step Two (if android):

getAndroidPermission = async () => {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
      );
      const grantedRead = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE
      );

      if (
        granted === PermissionsAndroid.RESULTS.GRANTED &&
        grantedRead === PermissionsAndroid.RESULTS.GRANTED
      ) {
        this.downloadBill();
      } else {
        Alert.alert(
          "Permission Denied!",
          "You need to give storage permission to download the file"
        );
      }
    } catch (err) {
      console.warn(err);
    }
  };

Step Three:

downloadBill = async () => {
    this.setState({ loading: true });
    let billId = this.state.billId;
    let user = await AsyncStorage.getItem("user");
    let parseUser = JSON.parse(user);
    let userToken = parseUser.token;

    RNFetchBlob.config({
      addAndroidDownloads: {
        useDownloadManager: true,
        notification: true,
        path:
          RNFetchBlob.fs.dirs.DownloadDir +
          "/" +
          `billID_${this.state.billId}.pdf`,
        mime: "text",
        description: "File downloaded by download manager.",
        appendExt: "pdf",
        trusty: true,
      },
    })
      .fetch("GET", `${config.apiUrl}/crm/getbillfile/${billId}`, {
        Authorization: "Bearer " + userToken,
      })
      .then((resp) => {
        let pdfLocation =
          RNFetchBlob.fs.dirs.DocumentDir +
          "/" +
          `billID_${this.state.billId}.pdf`;

        RNFetchBlob.fs.writeFile(pdfLocation, resp.data, "base64");

        FileViewer.open(pdfLocation, {
          onDismiss: () => this.setState({ loading: false }),
        });
      });
  }; 

I have added the following permissions in the android manifest file, and also linked re-fetch-blob manually:

 <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  <uses-permission android:name="android.permission.DOWNLOAD_WITHOUT_NOTIFICATION" /> 
  <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>

When I run the code it downloads the file to the correct location but displays a warning stating bad base64 and the PDF shows as invalid. The above code works fine on iOS.

Any help would be appreciated.

ahmed-rafiullah commented 3 years ago

Bump - I have the same problem

isipisi89 commented 2 years ago

same here ......

ardiansyaherwin commented 2 years ago

@niall-cooley did you find the solution? same here