react-native-blob-util icon indicating copy to clipboard operation
react-native-blob-util copied to clipboard

could not be written; error: (null) iOS

Open fonderkin opened this issue 1 year ago • 9 comments

Hello! When I try to write a file from base64, I get an error

[Error: File '/Users/.../Data/Application/560E644D-B059-4CE5-A128-EF68EEFD7D6D/Library/Caches/1688703508435.pdf' could not be written; error: (null)]

iOS 16.4 "react": "18.2.0", "react-native": "0.71.8", "react-native-blob-util": "^0.18.3",


      const filename = new Date().getTime() + '.pdf';
      const file = 'data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKMSAw...'
      const cacheFile = ReactNativeBlobUtil.fs.dirs.CacheDir + '/' + filename;
      ReactNativeBlobUtil.fs
      .writeFile(cacheFile, file, 'base64')
      .then(() => {
         console.log('write');
      })
      .catch(async (error) => {
        console.log(error);
      });

fonderkin avatar Jul 07 '23 04:07 fonderkin

I am having the same problem. Tried react-native-blob-util 0.18.3 and 0.17.0, both had the same error. It's a critical error since I can't leave customers unable to download. I may have to move back to rn-fetch-blob.

feng-yu-healthbank avatar Jul 14 '23 07:07 feng-yu-healthbank

Are you using new or old archiektur? And is it reproducable with your minimal code snippet?(if I use a correct base64 string)

RonRadtke avatar Jul 15 '23 08:07 RonRadtke

Android

newArchEnabled=false
hermesEnabled=false

ios

use_frameworks! :linkage => :static

packages

"react": "18.2.0",
"react-dom": "18.2.0",
"react-error-boundary": "^4.0.2",
"react-native": "0.71.4",

code:

import RNFetchBlob from 'react-native-blob-util';

const downloadInvoice = async () => {
    try {
      const filename = \`invoice-${invoiceUrl.split('/').pop()}\`;
      const { config, fs } = RNFetchBlob;
      const directory = Platform.OS === 'ios' ? fs.dirs.CacheDir : fs.dirs.DownloadDir;

      const path = `${directory}/${filename}`;
      const response = await config({
        fileCache: true,
        path,
        addAndroidDownloads: {
          useDownloadManager: true,
          notification: true,
          path: `${directory}/${filename}`,
          description: 'Downloading.',
        },
      }).fetch('GET', invoiceUrl, {
        Authorization: `Bearer ${token}`,
      });
      const { status } = response.info();
      if (status !== 200) {
        throw `Error downloading invoice. Status: ${status}`;
      }
      if (Platform.OS === 'ios') {
        await fs.writeFile(path, response.data, 'base64');
        RNFetchBlob.ios.openDocument(path);
        dispatch(resetSnackbar());
      } else {
        dispatch(
          setSnackbar({
            snackbarOpen: true,
            snackbarVariant: 'success',
            snackbarMessage: 'File successfully downloaded',
          })
        );
      }
    } catch (err) {
      global.Rollbar.error(err);
      dispatch(
        setSnackbar({
          snackbarOpen: true,
          snackbarVariant: 'error',
          snackbarMessage: 'There was an error downloading the file.',
        })
      );
    }
  };

I was downloading tax invoice in pdf from our company's server. sorry I can't create a reproducible repo, because in my code snippet the URL needs a bearer token to work.

Yesterday I have replaced import RNFetchBlob from 'react-native-blob-util'; into import from rn-fetch-blob and its now working flawlessly. No other change was made.

feng-yu-healthbank avatar Jul 15 '23 09:07 feng-yu-healthbank

Okay. The import looks rather odd since you didn't adjust the name. 0.16.4 works fine in my productive app. Didn't get to update libs there yet. I'll test the 0.18.3 and hope i can reproduce and fix it fast then

RonRadtke avatar Jul 15 '23 09:07 RonRadtke

In general the function is doing it what it should and works as expected. The error you're seeing is because writing to the file fails for unknown reason.

Edit: Managed to reproduce. The error apepars as soon as I prefix my base64 with data:application/pdf;base64,```` If I skip that part and only write the body data, so everything after data:application/pdf;base64,``` it works as expected.

RonRadtke avatar Jul 22 '23 19:07 RonRadtke

Is there an update on this? I have tried both, once with prefix and also without. Both lead to the same error as shown below.

"react-native-blob-util": "0.18.3"

Example 1 (with prefix):

const filenameWithPrefix = new Date().getTime() + '_withPrefix.pdf';
const fileWithPrefix = 'data:application/pdf;base64,JVBERi0xLjcKJeLjz9MKMSAw...';
const cacheFileWithPrefix = ReactNativeBlobUtil.fs.dirs.CacheDir + '/' + filenameWithPrefix;
ReactNativeBlobUtil.fs
  .writeFile(cacheFileWithPrefix, fileWithPrefix, 'base64')
  .then(() => {
    console.log('success');
  })
  .catch(async (error) => {
    console.log(error);
  });

leads to: [Error: File '/var/mobile/Containers/Data/Application/FD3B787E-A5CE-4284-927A-B568EDF50C4B/Library/Caches/1695999800777_withPrefix.pdf' could not be written; error: (null)]

Example 2 (without prefix):

const filenameWithoutPrefix = new Date().getTime() + '_withoutPrefix.pdf';
const fileWithoutPrefix = 'JVBERi0xLjcKJeLjz9MKMSAw...';
const cacheFileWithoutPrefix = ReactNativeBlobUtil.fs.dirs.CacheDir + '/' + filenameWithoutPrefix;
ReactNativeBlobUtil.fs
  .writeFile(cacheFileWithoutPrefix, fileWithoutPrefix, 'base64')
  .then(() => {
    console.log('success');
  })
  .catch(async (error) => {
    console.log(error);
  });

leads to: [Error: File '/var/mobile/Containers/Data/Application/FD3B787E-A5CE-4284-927A-B568EDF50C4B/Library/Caches/1695999800778_withoutPrefix.pdf' could not be written; error: (null)]

Phips0812 avatar Sep 29 '23 15:09 Phips0812

this did the trick for me, I think line endings are playing a role

const regex = /^data:image\/jpeg;base64,/

 await fs.writeFile(
      fileCache,
      image.replace(regex, '').replace(/\r?\n|\r/g, ''),
      'base64',
    )

johanmic avatar Nov 29 '23 00:11 johanmic

this did the trick for me, I think line endings are playing a role

const regex = /^data:image\/jpeg;base64,/

 await fs.writeFile(
      fileCache,
      image.replace(regex, '').replace(/\r?\n|\r/g, ''),
      'base64',
    )

It works for me! 3Q~

codecomeon avatar Feb 06 '24 04:02 codecomeon

The solutions here didn't work for me. In my case, the file is sometimes written, sometimes not. When I checked the base64 to see the difference, I noticed that the special padding character was missing. This doesn't cause issues on Android, but it does on iOS. I think it's a problem related to the package.

aslihanturkdonmez avatar Jul 11 '24 10:07 aslihanturkdonmez