react-native-fetch-blob multipart data image upload issue - javascript

I'm right now working on a react native project that have a taking image and upload function, and I'm using react-native-fetch-blob for passing multipart data to upload a single file. However, it seems to be not passing any data to my api.
I'm also using react-native-camera for capturing image. According to some usage of that module, my project is able to capture image and display the image by calling this function.
this.camera.capture({ metadata: options })
.then((data) => {
console.log("image path: ", data.path);
})
.catch(err => console.error(err));
Then I got the result like this,
image path: /var/mobile/Containers/Data/Application/.../AE1E52F0-8522-44D5-8603-21FB4EC9EAF9.jpg
So I used RNFetchBlob with this path to send image to my api like this,
RNFetchBlob.fetch(
'POST',
[url],
{
Authorization: jwtToken,
'Content-Type': 'multipart/form-data'
},
[
{
name: 'file',
filename: 'AE1E52F0-8522-44D5-8603-21FB4EC9EAF9.jpg',
type: 'image/jpeg',
data: RNFetchBlob.wrap('/var/mobile/Containers/Data/Application/.../AE1E52F0-8522-44D5-8603-21FB4EC9EAF9.jpg')
}
]
).then((response) => {
console.log("res: ", response.text());
})
.catch((error) => {
console.log(error);
});
After that, I checked the request that I can get from my API, it shows like this:
{
host: 'localhost:3000',
connection: 'close',
'content-type': 'multipart/form-data; charset=utf-8; boundary=RNFetchBlob1881293472',
'user-agent': 'app/1 CFNetwork/811.5.4 Darwin/16.6.0',
accept: '*/*',
'accept-language': 'zh-tw',
authorization: 'JWT eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJ1c2VySWQiOiI1OTUxMzYxZDBkMTk3MjczNjNiMzRhN2EiLCJ1c2VyVHlwZSI6InVzZXIiLCJpYXQiOjE0OTg0OTQ1MTUsImV4cCI6MTQ5OTA5OTMxNX0.8vhDJtFugi4OQAJ48PTsBlAp8bw6x__KwOXvk6xuYW8',
'content-length': '552434',
'accept-encoding': 'gzip, deflate'
}
But I tried console my req.body I got empty object {} from that. Can you give me some suggestion on that? Thank you~
I'm using "react-native-fetch-blob": "^0.10.5" and "node": "v6.10.2"

Related

Cypress giving error about promise while sending api request

I got a promise error by cypress; what should I do? What am I missing?
let woID = 0
let woCoordinate = 0
let keyCloakToken = 0
class utils {
createIncidentViaAPI() {
keyCloakToken = localStorage.getItem('keycloak-token')
fetch('https://URL', {
headers: {
accept: 'application/json, text/plain, */*',
authorization: 'Bearer ' + keyCloakToken,
'content-type': 'application/json;charset=UTF-8',
},
body: '{"description":"keycloak","type":"SY","startDate":"2022-08-14T12:19:00.000Z","locationAddress":"Japanese Pagoda Ohio Dr SW","latitude":38.88366120709875,"longitude":-77.04149404953358,"sourceType":"CALL"}',
method: 'POST'
})
.then((res) => res.json())
.then((out) => {
cy.log(out.data.incidentId)
})
}
the fetch request that you can see at the top is working stable without problem but I having some issues to work API request at the bottom.
the important thing is that when I send createWorkOrderViaAPI() request I should have to wait 60-70 seconds because the system responds every 60 secs. That's why I tried to use then block. by the way, I tried some different options too but I didn't solve the promise problem.
createWorkOrderViaAPI() {
cy.request({
url: 'URL',
method: 'POST',
headers: {
properties: 'wonum',
'Content-Type': 'application/json',
MAXAUTH: 'autpassword',
Authorization: 'Basic ' + 'autpassword'
},
body: {
description: 'test request',
}
}).then((res) => {
woID = res.body.wonum
//here i want get some numbers then i want to use these second API request which you can see //inside then block.
}).then((out)=>{
fetch('https://URL', {
headers: {
accept: 'application/json, text/plain, */*',
'accept-language': 'tr-TR,tr;q=0.9,en-US;q=0.8,en;q=0.7',
authorization: 'Bearer ' + keyCloakToken,
},
body:
'{"statusList":"sortDirection":"DESC","archivalTypeList":["ACTIVE"],"countByField":"NEIGHBORHOOD","searchText":"' +
---> i want use woID number here ---> woID +
'}',
method: 'POST'
}).then((res) => {
woCoordinate = res.body.wkt
cy.log(woCoordinate)
})
})
}
when I run this code i getting error message by cypress about promise I leaving the message doc here
especially when I change cy.request to fetch error just disappears but fetch is not working not creating order as i want.
The problem is that you cant use cy. methods inside of any then block.
.then(()=>{
don't use here any cypress method
})
I separated my own API requests and deleted necessary cypress requests then it worked.

http POST request response with "status": 200 but with an empty object

I am trying to use an API with HTTP POST request and It seems to work but when I get the response it's empty.
The API should receive base64 encoded image inside the body.
The argument imageToRead coming from a promise returned with the Camera component from react-native-camera. I'm not sure maybe the problem there?
This is the content:
imageToRead = "/var/mobile/Containers/Data/Application/01B81FC9-B171-11GB-9B48-9D06F89B175A/Documents/3A997ACD-D63C-41BD-9041-FDB834A0672A.jpg"
This API can also receive formData files and that how I tested it with and it went great in Node environment. But because my application is a native iOS application, I had to use other tools (like React Native) and can not use the same ones.
Code to test the API in Node:
var formData = {image: fs.createReadStream('/Users/Desktop/APITest/img/testOCR8.jpg')};
request.post({
url:'${url}',
formData: formData},
(err, httpResponse, body) => {
if (err) {
return console.error('upload failed:', err);
}
console.log(body);
});
You can see I use fs.createReadStream from the fs module to create stream of the file and then use it inside the request body.
I couldn't replicate the same thing using React Native (if you have a solution so I could do it with React Native it would be even better!!)
So I tried deferent way and tried to encode the file I got from the camera.capture() method that come with react-native-camera to base64 and to place it inside the body but the response I got is empty without any errors, just an empty object.
Code with React Native:
recognise = (imageToRead) => {
RNFetchBlob.fs.readFile(imageToRead , 'base64')
.then((data) => {
fetch('${url}',{
method: "POST",
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json'
},
body: data // the body contain the encoded image
})
.then((res) => { // promise returned with the response from the API
console.log(`i am the base64Image: ${data}`)
console.log('i am response', res)
})
.catch((errInFetch) => { // catch any error in the API
console.log('i am error:', errInFetch)
})
})
.catch((err) => {
console.log(err);
})
}
Response:
{ type: 'default',
status: 200,
ok: true,
statusText: undefined,
headers:
{ map:
{ server: [ 'nginx/1.10.3' ],
'content-type': [ 'application/json; charset="utf-8"' ],
'access-control-allow-origin': [ '*' ],
date: [ 'Thu, 10 May 2018 10:17:48 GMT' ],
'access-control-allow-headers': [ 'x-requested-with' ],
'content-encoding': [ 'gzip' ],
'content-length': [ '237' ],
connection: [ 'keep-alive' ] } },
url: 'https://api.openalpr.com/v2/recognize_bytes?secret_key=key&country=eu',
_bodyInit:
{ _data:
{ size: 371,
blobId: '5080ACA4-5D13-469C-B755-96B06A161FC6',
type: 'application/json',
offset: 0,
name: 'recognize_bytes' } },
_bodyBlob:
{ _data:
{ size: 371,
blobId: '5080ACA4-5D13-469C-B755-96B06A161FC6',
type: 'application/json',
offset: 0,
name: 'recognize_bytes' } } }
I hope someone can help with this. I have struggle with it for so long time.
fetch returns a promise containing the response (a Response object). then you again need to parse that using response.json() which returns promise resolving JSON.
fetch(url, {
body: JSON.stringify(data),
cache: 'no-cache',
headers: {
'user-agent': 'Mozilla/4.0 MDN Example',
'content-type': 'application/json'
},
method: 'POST', // *GET, POST, PUT, DELETE, etc.
})
.then(response => response.json())
for more info : read
.then((res) => {
console.log(`i am the base64Image: ${data}`)
console.log('i am response', res)
return res.json();
})
.then(res => {
console.log(res);
})
.catch((errInFetch) => { // catch any error in the API
console.log('i am error:', errInFetch)
})
Fetch response body returns a Promise that will be resolved by json().
So you can get your real data from res.json().
The 200 status is for a success get http request. Your API should return status 201 for post with a message instead of 200, for example:
res.status(201).send(data);
full example
also, you can look at the status 201 description

Saving an image from Node's readStream with client Javascript

I have been struggling with this one for a while now, and need your guys help! I am trying to streamline the process of downloading a report from my website. With node this is fairly straightforward with a readStream, like so:
router.post('/report', (req, res) => {
const filename = 'test.png';
const filePath = path.join(__dirname, filename);
fs.exists(filePath, exists => {
if (exists) {
const stat = fs.statSync(filePath);
res.writeHead(200, {
'Content-Type': 'image/png',
'Content-Length': stat.size,
'Content-Disposition': 'attachment; filename=' + filename,
});
fs.createReadStream(filePath).pipe(res);
} else {
res.writeHead(400, { 'Content-Type': 'text/plain' });
res.end('ERROR File does NOT Exists');
}
});
});
Now if I try this with Postman or some other API tester, it works perfectly, the file is downloaded and saved correctly. Now I am struggling to get this to work my front-end. I am currently running AngularJS and have tried to use FileSaver.js as a way to take this data and save it, however it never works. The file is saved, but the data is unreadable, aka the image previewer says the image is broken. I think I am creating the Blob incorrectly?
function exportReport(_id) {
this.$http
.post(
'/api/report',
{ _id },
{
headers: {
'Content-type': 'application/json',
Accept: 'image/png',
},
}
)
.then(data => {
console.log(data);
const blob = new Blob([data], {
type: 'image/png',
});
this.FileSaver.saveAs(blob, 'testing.png');
});
}
The console log result is as so:
Object {data: "�PNG
↵↵
IHDRRX��iCCPICC Profi…g�x #� #������Z��IEND�B`�", status: 200, config: Object, statusText: "OK", headers: function}
Am I suppose to decode the object.data?
Try adding responseType: 'blob' to the request and omit creating a new blob:
function exportReport(_id) {
this.$http
.post(
'/api/report',
{ _id },
{
headers: {
'Content-type': 'application/json',
Accept: 'image/png',
},
responseType: 'blob'
}
)
.then(data => {
console.log(data);
this.FileSaver.saveAs(data.data, 'testing.png');
});
}

WP REST API Media upload using fetch()

I'm trying to use fetch() to perform a media upload in WP Rest API using JS (React Native).
Here's what I've done so far:
fetch('https://www.example.fr/wp-json/wp/v2/media', {
method: 'post',
headers: new Headers({
'Content-Type': 'image/jpeg',
'Authorization': 'Basic d3GtcmVzdC1sdfGktY2xpZW50Onefepbl9hdh90aWJldA==',
'Content-Disposition': 'attachment; filename="user-'+userId+'.jpg"'
}),
body: imageBase64Data
})
.then(function (response) {
console.log(response);
});
imageBase64Data is set like this:
let imageBase64Data = 'data:image/png;base64,'+ imageData;
and imageData is react-native-image-picker response.data: https://github.com/react-community/react-native-image-picker#the-response-object
Here's my issue: the media is created successfully on my WP, but the image is empty (no data, around 15B). So I'm guessing something is messing up with the data I'm sending as the body of my request. But I don't know what.
Any ideas?
For the record, here's how I finally ended up with this issue, using react-native-fetch-blob module:
RNFetchBlob.fetch('post', 'https://www.example.fr/wp-json/wp/v2/media',
{
'Content-Type': 'image/jpeg',
'Authorization': 'Basic dqdsfqsdfpbl9hqsdfdsfWJldA==',
'Content-Disposition': 'attachment; filename="user-'+userId+'.jpg"'
}
,imageUri) // imageUri = RNFetchBlob.wrap(imageUri);
.then(function (response) {
console.log(response); // returns a 201 response with id of the attached media
});

Uploading file via PUT method in react-native

I am trying to upload file(image) from my react-native app to backend server. The RESTFUL backend server accepts file send via PUT method on a specific url. I am stuck on react-native trying to find the proper way to send file via PUT method.
I am trying to replicate behavior of
curl -X PUT -T "/path/to/file" "http://myputserver.com/puturl.tmp"
I found XMLHttpRequest method of doing this on a browser but won't work on react-native. Have anyone gone through this please help!!!
fetch('https://mywebsite.com/endpoint/', {
method: 'PUT',
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
}),
})
.then((response) => response.json())
.then((responseJson) => {
alert(responseJson)
})
.catch((error) => {
console.error(error)
})
reference
reference 2
Fetch
Use the fetch api, which is supported by React Native.
Below is an example of the official documentation.
Fetch supports PUT, according to the specs.
fetch('https://mywebsite.com/endpoint/', {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'application/json',
},
body: JSON.stringify({
firstParam: 'yourValue',
secondParam: 'yourOtherValue',
})
})
You can use the PUT like the answer above. You might be missing the 'Content-Type': 'multipart/form-data;'.
const config = {
method: 'PUT',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data;',
'Authorization': 'Bearer ' + 'SECRET_OAUTH2_TOKEN_IF_AUTH',
},
body: data,
}
Some more information in this blog post:
http://snowball.digital/Blog/Uploading-Images-in-React-Native

Categories