react-nativezipreact-native-fetch-blob

How to send `application/zip` in react-native


I want to generate a zip file and then POST it up. I am trying to leverage this lib JSZip to create a zip with several files in it. Here is what I have right now.

handlePendingItems = async (routeId: number) => {
    try {
      await dbClient.addLogLine(`Need to delete photos.`);
      const [debugLogs, pendingTasks, pendingUploads] = await this.getPendingItems();
      const dbVersion = await dbClient.getUserSchemaVersion();
      let appInfo = `Database Version = ${dbVersion}\n`;
      appInfo += `App Version = ${version}`;
      const zip = new JSZip();
      zip.file('app-info.txt', appInfo);
      if (debugLogs.length) {
        const debugLogsCsv = convertDataToCSV(debugLogs);
        zip.file('debug-logs.csv', debugLogsCsv);
      }
      if (pendingTasks.length) {
        const pendingTasksCsv = convertDataToCSV(pendingTasks);
        zip.file('pending-tasks.csv', pendingTasksCsv);
      }
      if (pendingUploads.length) {
        const pendingUploadsCsv = convertDataToCSV(pendingUploads);
        zip.file('pending-uploads.csv', pendingUploadsCsv);
      }
      const test = await zip.generateAsync({ type: 'binarystring' });
      console.log(test);
      const res = PhotoService.uploadLogs(routeId, test);

      // const zipFile = await zip.generateAsync({
      //   type: 'blob',
      //   compression: 'DEFLATE',
      //   compressionOptions: {
      //     level: 9
      //   }
      // });
    } catch (error) {
      console.log(error);
    }
  };

I can't use the type: 'blob' in react-native, it throws an error as unsupported on this platform. That being said I am trying to use other types to pass to react-native-fetch-blob. To be posted via the following code.

  uploadLogs(driverRouteId: number, logs: string) {
    const store = getStore();
    const token = store.getState()?.auth?.token || '';

    return new Promise((resolve, reject) => {
      RNFetchBlob.fetch(
        'POST',
        `${API_HOST}driver/route/${driverRouteId}/logs`,
        {
          'Content-Type': 'application/zip',
          Authorization: `Bearer ${token}`
        },
        logs
      ).then(
        (res) => {
          console.log(res);
          resolve(res);
        },
        (err) => {
          console.log(err);
          debugger;
          reject(err);
        }
      );
    });
  }

I read that fetch blob will attempt to parse base64 string if the content-encoding is a specific type which in this case has to be application/zip (so no parsing in this case) so I am trying to call generateAsync with type string however, the zip the file the server stores is in an unsupported format. How can I generate the zip file containing the three csv files and the txt file and send it using either fetch blob or just plain axios in react-native.


Solution

  • Figured out a solution using a different library to zip.

    npm install react-native-zip-archive --save
    npm install react-native-fs --save
    npm install rn-fetch-blob --save
    import RNFetchBlob from 'rn-fetch-blob';
    import { zip } from 'react-native-zip-archive';
    import RNFS from 'react-native-fs';
    
    const pathsToZip = [];
    const zipPath = `${RNFS.DocumentDirectoryPath}/test.zip`;
    const appInfo = 'App info string to put in txt file'
    const appInfoPath = RNFS.DocumentDirectoryPath + '/appInfo.txt';
    await RNFS.writeFile(appInfoPath, appInfo, 'utf8');
    pathsToZip.push(appInfoPath);
    await zip(pathsToZip, zipPath);
    
    await uploadLogs(zipPath) {
        return new Promise((resolve, reject) => {
          RNFetchBlob.fetch(
            'POST',
            `postpath`,
            {
              'Content-Type': 'application/zip',
            },
            RNFetchBlob.wrap(zipPath)
          ).then(
            (res) => {
              console.log(res);
              resolve(res);
            },
            (err) => {
              console.log(err);
              debugger;
              reject(err);
            }
          );
        });
    }