1

我最近一直在将上传文件功能实现到 React-native 中,并遇到了一个错误,我需要将二进制文件数据发布到请求正文中。

首先,我检查了Postman的工作原理,并将这个 API 测试到我发送的邮递员Authorizationuid请求标头中,body并将成为带有=的 Form-Datadocumentbinary file

见下文是document我们能够在 Postman 中选择文件对象的关键。

邮递员请求正文表示。 文档是文件类型。

现在这个 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,所以当我选择任何文件时,我得到的对象就像,

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

我需要通过 API 调用将此文件(例如 plist)上传到/adDocument该端点期望请求正文为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.

我在请求正文中看到的是,

在此处输入图像描述

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

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

4

1 回答 1

2

这确实是问题,React-native debugger而不是实际的实施问题。如此处所述=> https://github.com/jhen0409/react-native-debugger/blob/master/docs/network-inspect-of-chrome-devtools.md,调试器与 FormData 和任何传入的东西混在一起[object Object]由于uri属性,FormData 变成字符串。

我已关闭调试并在设备和模拟器上进行了尝试,以下代码按预期工作。无需将文件显式转换为 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  };
  }
}

就如此容易 :)。

于 2021-03-05T11:57:05.643 回答