0

I have to generate a CSV file, pluck it from local storage, upload it to AWS, then mail the link to the user for access.

iOS is generating the CSV, uploading successfully, and emailing correctly, while Android is not.

I have tried every combination I can think of to get the file from local storage/scoured multiple forums and stackoverflow posts, changes the write directories, but nothing comes close to answering my questions.

The file permissions are set correctly with Read/Write External Storage, I have a prompt to ensure that the user accepts the terms of access, and have tested to make sure the directory is working properly.

For this particular app, we are using React Native v 0.57

Code is split between two functions:


  async function requestFileStoragePermission() {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
        {
          'title': 'External Storage',
          'message': 'This app needs permission to save csv files to your device.'
        }
      )
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        console.log("You can save files")
      } else {
        console.log("Save files permission denied")
      }
    } catch (err) {
      console.warn(err)
    }
  }

  async function requestFileReadingPermission() {
    try {
      const granted = await PermissionsAndroid.request(
        PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
        {
          'title': 'Read csv Files',
          'message': 'This app needs permission to read csv files from your device.'
        }
      )
      if (granted === PermissionsAndroid.RESULTS.GRANTED) {
        console.log("You can read files")
      } else {
        console.log("Read files permission denied")
      }
    } catch (err) {
      console.warn(err)
    }
  }

  if(Platform.OS === 'android') {
    requestFileStoragePermission()
    requestFileReadingPermission()
  }

  // write the current list of answers to a local csv file
  const pathToWrite = `${RNFetchBlob.fs.dirs.DocumentDir}/Employee_Timesheet1.csv`;


  RNFetchBlob.fs
    .writeFile(pathToWrite, csvString, 'utf8')
    .then(() => {
      console.log('Upload phase')
      fileLink = uploadCSV(pathToWrite, 'Employee_Timesheet1.csv');
        return fileLink;
    })
    .then((res) => {
      Mailer.mail({
        subject: `Timesheet for ${employeeName}`,
        recipients: ['my@email.com'],
        ccRecipients: [],
        bccRecipients: [],
        body: `<b>Employee Timesheet for ${employeeName}</b>/n<b>Click here to download ${res}</b>`,
        isHTML: true
      }, (error, event) => {
        console.log(error, event);
        Alert.alert(
          error,
          event,
          [
            { text: 'Ok', onPress: () => console.log('OK: Email Error Response') },
            { text: 'Cancel', onPress: () => console.log('CANCEL: Email Error Response') }
          ],
          { cancelable: true }
        )
      });
    })
    .catch(error => console.error(error));
}

//And then there's a function that handles uploading to AWS: 


export function uploadCSV(csvPath, fileName) {

  let type = 'text/csv'

  const fileInformation = {
    uri: csvPath,
    name: fileName,
    type: type
  }


//Options omitted due to sensitive information.

  let fileLink = RNS3.put(fileInformation, options)
    .then(response => {
      if (response.status !== 201) {
        throw new Error(response.status, response.status);
      } else {
         return response.body.postResponse.location;
      }
    })

    return fileLink;
}

When I run the following code, I get the following error:

status: 0
text: "Could not retrieve file for uri /data/user/0/com.app/files/Employee_Timesheet1.csv"

Error Message Android

const fileInformation = {uri : ${Platform.OS === 'android' ? 'file://' : ''}${csvPath}, name : fileName, type : type}
hong developer
  • 13,291
  • 4
  • 38
  • 68

1 Answers1

0

[Content][1] should be an Array or String.

Example

const PATH_TO_ANOTHER_FILE = "http://www.example.com/exam.jpg"
// write UTF8 data to file
RNFetchBlob.fs.writeFile(PATH_TO_WRITE, 'foo', 'utf8')
              .then(()=>{ ... })
// write bytes to file
RNFetchBlob.fs.writeFile(PATH_TO_WRITE, [102,111,111], 'ascii')
              .then(()=>{ ... })
// write base64 data to file
RNFetchBlob.fs.writeFile(PATH_TO_WRITE, RNFetchBlob.base64.encode('foo'), 'base64')
              .then(()=>{ ... })
// write file using content of another file
RNFetchBlob.fs.writeFile(PATH_TO_WRITE, PATH_TO_ANOTHER_FILE, 'uri')
              .then(()=>{ ... })

hong developer
  • 13,291
  • 4
  • 38
  • 68
  • Turns out, my code was correct with creating the file, but RNS3 wasn't pointing to the right file path. I had to add the following line to the fileInformation constant: ``` const fileInformation = { uri: `${Platform.OS === 'android' ? 'file://' : ''}${csvPath}`, name: fileName, type: type }``` – Roger winright Aug 14 '19 at 14:34
  • Why do I add file path when I am on Android? – hong developer Aug 14 '19 at 15:14
  • I thought it was strange as well. I guess it has something to do with the Android file system not recognizing you're trying to access a file from the root of the device to the file itself whereas iOS knows that you're trying to access a file through a file-path and therefore retrieves the path from root to the file? – Roger winright Aug 14 '19 at 17:38