I have been implementing upload file functionality into React-native recently and came across an error where I need to post binary file data into Request body.
First of all, I have checked how Postman works and I tested this API into postman where I send Authorization
and uid
into request headers and body
will be Form-Data with document
= binary file
.
See below is document
key where we are able to select file object in Postman.
Now this Postman request succeeds this way and if I check relevant code for NodeJs-Axios, it's just as added here.
This code is from Postman intended just for explanation.
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);
});
As we are not able to use the same function added above for React-native and I have used react-native-document-picker
, when I pick any file, the object I get is like,
{
"size":1173,
"fileCopyUri":"file:///Users/Local_File_Path.plist",
"name":"File_Name.plist",
"uri":"file:///Users/Local_File_Path.plist"
}
I need to upload this file (e.g. plist) via API call to /adDocument
endpoint where this endpoint expects request body as document: (binary data)
.
So, here is my main function for addDocument API call which needs to be corrected to send proper data to 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 };
}
}
I always receive failure with this function using any of the above mentioned methods, readStreamData
, readFileData
or wrapData
. The reason is, I am never able to pass binary data into document
.
What I see in request body is like,
Here, [object Object]
is a string and not an object and so, my API call throws me error stating, data missing. It always passes string event I use 'Blob()'.
So, I want to know what I am doing wrong here so my request body is not passing binary data. Please send me any pointers on the topic so I can reach to the solution.
That was really issue with React-native debugger
and not the actual implementation issue. As mentioned here => https://github.com/jhen0409/react-native-debugger/blob/master/docs/network-inspect-of-chrome-devtools.md, the debugger messes around with FormData and whatever being passed into FormData turns as [object Object]
string due to uri
property.
I had turned off debugging and tried on both device and simulator, where following code worked as expected. No need to explicitly convert file into 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 };
}
}
As simple as that :).