React-native RNFetchBlob: Axios Post 请求发送字符串而不是二进制数据

React-native RNFetchBlob: Axios Post request sends string instead of binary data

我最近一直在将上传文件功能实现到 React-native 中,但遇到一个错误,我需要将二进制文件数据 post 到请求 body.

首先,我检查了 Postman 是如何工作的,我测试了这个 API 到 postman 我发送 Authorizationuid 到请求 headers 和 body 将是 Form-Datadocument = binary file.

下面是 document 键,我们可以在 Postman 中 select 文件 object。

现在这个 Postman 请求通过这种方式成功了,如果我检查 NodeJs-Axios 的相关代码,它就像在此处添加的一样。

此代码来自 Postman,仅供说明之用。

var axios = require('axios');
var FormData = require('form-data');
var fs = require('fs');
var data = new FormData();
data.append('document', fs.createReadStream('LOCAL_PATH_TO_FILE/Screenshot 2021-01-28 at 12.26.32 PM.png'));

var config = {
  method: 'post',
  url: 'API_BASE/addDocument/',
  headers: { 
    'Authorization': 'Firebase_ID_Token', 
    'uid': 'Firebase_User_ID', 
    ...data.getHeaders()
  },
  data : data
};

axios(config)
.then(function (response) {
  console.log(JSON.stringify(response.data));
})
.catch(function (error) {
  console.log(error);
});

由于我们无法使用上面为 React-native 添加的相同功能,而我使用了 react-native-document-picker,当我选择任何文件时,我得到的 object 就像,

{
 
    "size":1173,
    "fileCopyUri":"file:///Users/Local_File_Path.plist",
    "name":"File_Name.plist",
    "uri":"file:///Users/Local_File_Path.plist"
}

我需要通过 API 调用 /adDocument 端点上传此文件(例如 plist),该端点期望请求 body 作为 document: (binary data).

所以,这是我的 addDocument API 调用 的主要功能,需要更正才能将正确的数据发送到 API.

import RNFetchBlob from 'rn-fetch-blob';
var RNFS = require('react-native-fs');

async uploadFileData (fileData) {
  try {
    console.log("***** uploadFileData parameters =>>>>> ", fileData);

    const mainPath = fileData.uri.replace("file://", "");
    let readStreamData = await RNFetchBlob.fs.readStream(mainPath, 'base64');
    let readFileData = await RNFS.readFile(mainPath);
    let wrapData = RNFetchBlob.wrap(mainPath);
    
    let data = new FormData();
    data.append('document', readStreamData, {'name': fileData.name});
    //data.append('document', new Blob([readFileData]), {'name': fileData.name});
    //data.append('document', readFileData, {'name': fileData.name});
    
    const apiHeader = {
        'Authorization': 'Google_ID_Token',
        'uid': 'Google_User_ID',
        'Content-Type': 'multipart/form-data',
        'Cache-Control' : 'no-store'
    };

    const res = await axios({ 
      method: 'POST',
      headers: apiHeader,
      data: data,
      baseURL: 'BASE_URL',
      url: '/addDocument/'
    });
  
    console.log("document/addDocument =>>>>> ", res);
    return res;
  } catch (e) {
    console.log("xxxxxxx document/addDocument Error =>>>>> ", e);
    return {  error: e  };
  }
}

使用上述任何方法 readStreamDatareadFileDatawrapData,此功能总是失败。原因是,我永远无法将二进制数据传递到 document.

我在请求中看到的body是这样的,

在这里,[object Object] 是一个字符串而不是 object,因此,我的 API 调用抛出错误说明,数据丢失。它总是传递我使用 'Blob()'.

的字符串事件

所以,我想知道我在这里做错了什么,所以我的请求 body 没有传递二进制数据。请将有关该主题的任何指示发送给我,以便我找到解决方案。

那是 React-native debugger 的真正问题,而不是实际的实施问题。正如此处提到的 => https://github.com/jhen0409/react-native-debugger/blob/master/docs/network-inspect-of-chrome-devtools.md,调试器会乱用 FormData,并且由于 uri 属性.

,传递给 FormData 的任何内容都会变成 [object Object] 字符串

我已关闭调试并在设备和模拟器上进行了尝试,以下代码按预期工作。 无需显式将文件转换为 blob。

async simpleFileUpload (fileData) {
  try {
    console.log("***** uploadFileData parameters =>>>>> ", fileData);

    const mainPath = fileData.uri.replace("file://", "");
    const file = {
      uri: mainPath,
      type: fileData.type,
      name: fileData.name || fileData.uri.substr(fileData.uri.lastIndexOf('/') + 1)
    };

    let formData = new FormData();
    formData.append('document', file);
    
    const res = await axios({ 
      method: 'POST',
      headers: this.apiHeaderUpload(),
      data: formData,
      baseURL: 'http://103.53.72.244:9091/api',
      url: '/document/addDocument/'
    });

    console.log("document/addDocument =>>>>> ", res);
    //alert('uploadFileData::Upload Successful >>> ' + JSON.stringify(res));
    return res;
  } catch (e) {
    console.log("xxxxxxx document/addDocument Error =>>>>> ", e);
    //alert('uploadFileData::Upload Error >>> ' + JSON.stringify(e));
    return {  error: e  };
  }
}

就这么简单:)。