skip to Main Content

I’m trying to use the files:get method from Google Drive API to download an image, and store it into a path using RNFS. Currently, I’m able to get a correct response (verfied using Postman as well), but I don’t know how to handle the response to save it as a .jpg file.

Here are my code blocks for the axios call:

downloadActivityCard: async function (id) {
    try {
      const params = {
        //  fields: 'kind,driveId,mimeType,id,name,teamDriveId,thumbnailLink,webContentLink,modifiedTime',
        alt: 'media',
        responseType: 'arraybuffer',
      };
      const dirPath = MAINDIRECTORY + '/FeaturedActivityCards/' + id;
      const filePath = `${dirPath}/cardImage.jpg`;
      let card = {};

      //check if file exists
      if (await checkFileExists(filePath)) {
        throw new Error('This Activity Card is already downloaded');
      }

      //set up the get URL, then call axios for response
      const downloadUrl =
        DRIVE_API_URLS.SEARCH_FILES +
        '/' +
        id +
        DRIVE_API_URLS.SEARCH_PARAMETERS;

      const response = await axios.get(downloadUrl, { params }).catch(error => {
        console.error('ERROR IN DOWNLOADING ACTIVITY CARD: ' + error);
      });

      card = response.data;
      //make directory for the newly downloaded card, write the card into this path and return
      await makeDirectory(dirPath);
      await writeFile(true, filePath, card);
      return filePath;
    } catch (e) {
      console.log('ERROR IN DOWNLOADING ACTIVITY CARD: ' + e);
    }
  }

and the RNFS.writeFile:

export async function writeFile(isImage, filepath, content) {
  const options = {
    encoding: '',
  };
  if (isImage) {
    options.encoding = 'base64';
  } else {
    options.encoding = 'utf8';
  }
  return RNFS.writeFile(filepath, content, options.encoding)
    .then(success => {
      console.log(`FILE WRITTEN!: ${filepath}`);
    })
    .catch(err => {
      console.log(`RNFS writeFile: ${err.message}`);
    });
}

When I try to write this response into a .jpg file, the file is saved in the correct directory under the correct name.

However, I’m not able to open up the image, despite changing the RNFS encoding argument to both ‘base64’ and ‘binary’. I’ve also tried different parameters within the GET call, but unsuprisingly, this doesn’t fix the problem.

Is there any issue in the way I am handling the GET response, and if so, how can I modify it to save the image recieved from the GET call?

2

Answers


  1. It is possible that the image file is being saved in a format that is unrecognized. In that case, you may need to convert the image data to a format that your device can recognize.
    Here is an example of how you could use this module to download an image from the Google Drive API and save it to your app’s file system:

    import RNFetchBlob, { FileDownload } from 'react-native-fetch-blob';
    import FileDownloadModule from '@react-native-community/file-download';
    import RNFS from 'rnfs';
    
    export async function downloadImage(imageUrl) {
      try {
        const response = await RNFetchblob.fetch('GET', imageUrl);
        const filePath = '/path/to/image.jpg';
        const fileName = 'image.jpg';
        FileDownloadModule.save(response, filePath, fileName);
      } catch (error) {
        console.error('There was an error while trying to download the image:',error);
      }
    }
    
    Login or Signup to reply.
  2. Although the answer of Molassay Vladimir is valid, I will add this here too.

    You are not handling the arraybuffer response from the Google Drive API correctly when writing the file using RNFS.writeFile.

    When you make a GET request to the Google Drive API with responseType: ‘arraybuffer’, the response will be an ArrayBuffer object that contains the raw bytes of the image data. In order to write this data to a file using RNFS.writeFile, you need to convert the ArrayBuffer to a base64-encoded string, which you can then write to the file using the ‘base64’ encoding option.

    Here is how you can do it:

    downloadActivityCard: async function (id) {
      try {
        const params = {
          alt: 'media',
          responseType: 'arraybuffer',
        };
        const dirPath = MAINDIRECTORY + '/FeaturedActivityCards/' + id;
        const filePath = `${dirPath}/cardImage.jpg`;
        let card = {};
    
        //check if file exists
        if (await checkFileExists(filePath)) {
          throw new Error('This Activity Card is already downloaded');
        }
    
        //set up the get URL, then call axios for response
        const downloadUrl =
          DRIVE_API_URLS.SEARCH_FILES +
          '/' +
          id +
          DRIVE_API_URLS.SEARCH_PARAMETERS;
    
        const response = await axios.get(downloadUrl, { params }).catch(error => {
          console.error('ERROR IN DOWNLOADING ACTIVITY CARD: ' + error);
        });
    
        // convert ArrayBuffer to base64-encoded string
        const base64Image = Buffer.from(response.data, 'binary').toString('base64');
    
        // write base64-encoded string to file using RNFS.writeFile
        await makeDirectory(dirPath);
        await writeFile(true, filePath, base64Image);
        return filePath;
      } catch (e) {
        console.log('ERROR IN DOWNLOADING ACTIVITY CARD: ' + e);
      }
    }
    
    

    With TextEncoder:

    
    // convert ArrayBuffer to base64-encoded string using TextEncoder
    const base64Image = btoa(new TextEncoder().encode(String.fromCharCode(...new Uint8Array(response.data))).toString('base64'));
    
    // write base64-encoded string to file using RNFS.writeFile
    await RNFS.writeFile(filePath, base64Image, 'base64');
    
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search