React Native how to upload multiple photos to server at once - react-native

I've tried to upload multiple images to server at a once by using fetch.
Here is my code chip.
chooseImage(){
ImagePicker.openPicker({
multiple: true,
waitAnimationEnd: false
}).then(images => {
var photos = []
images.map((image, i) => {
photos.push({
uri:image.path,
name: image.name,
type: 'image/jpg'
})
let source = {uri: image.path}
this.state.photos.push({image: source, check: true, hairstyle: '', price: ''})
})
var data = new FormData();
data.append('photos', photos)
const config = {
method: 'POST',
headers: {
'Accept':'application/json',
'Content-Type':'multipart/form-data;',
'Authorization': this.props.auth.token
},
body: data,
}
fetch("http://**.***.***.***/api/providers/uploadPhotos", config)
.then(res=>res.json()).then((res) => {
console.log("----------Response----------")
console.log(res)
this._getStylist()
this.setState({photo_take: false});
}).catch(err=>{
console.log("------------Error-----------")
console.log(err)
console.log("error in uploading image")
}).done()
}).catch(e => {
console.log(e);
});
}
When I try it, I get 200 response from server and photos doesn't upload to server actually.
I searched the solution a few days, but couldn't find the suitable solution.
Thanks for any suggestion.

I am new at react native but seems like you can loop throght images array to upload images Maybe you can add this post actions in promise array then you can be sure that every photo added to your storage. I use promise array methods while working on my node js server project its very useful.
Edit for example:
var photos=[];
var promise_array=[];
photos.forEach(function(photo){
const config = {
method: 'POST',
headers: {
'Accept':'application/json',
'Content-Type':'multipart/form-data;',
'Authorization': this.props.auth.token
},
body: photo,
}
promise_array.push(fetch("http://**.***.***.***/api/providers/uploadPhotos", config)
.then(res=>res.json()).then((res) => {
console.log("----------Response----------")
console.log(res)
this._getStylist()
this.setState({photo_take: false});
}).catch(err=>{
console.log("------------Error-----------")
console.log(err)
console.log("error in uploading image")
}).done())
})
Promise.all(promise_array);
Since fetch is a promise I can put in promise array. Maybe there is syntax error in example and I am not sure react native support promise methods fully but here is documentation for promise method I use https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise/all

Related

Fetch Post of formData with images works in iOS but on android returns 400 BAD REQUEST

`I am using fetch on react native to send a post request with a form data object on the body.
This code works on iOS but on android it returns a 400 BAD REQUEST and I get ERROR [SyntaxError: JSON Parse error: Unexpected EOF].
const buildFormData = () => {
const data = new FormData();
for (let i = 0; i < photoForm.photosToUpload.length; i++) {
console.log(photoForm.photosToUpload[i].uri)
data.append('photosToUpload', {
uri: photoForm.photosToUpload[i].uri,
name: photoForm.photosToUpload[i].fileName,
type: 'image/jpeg'
});
data.append("userForm", JSON.stringify(userForm));
console.log(data)
return data;
}
This is how I am building my form data.
export const createUser = (formData) => async (dispatch) => {
try {
const headers = {
'Content-Type': 'multipart/form-data'
};
const response = await fetch('https://c66d-2a02-a03f-a5a1-e400-1573-78c6-e019-e601.eu.ngrok.io' + '/create_user', {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
},
body: formData,
})
.then(response => response.json())
.then(responseJson => {
console.log(responseJson);
})
.catch(error => {
console.error(error);
});
Handle successful response
catch (error) {
Handle error
}
This is how I am sending the form data to my django server. I know the problem is in the form data because if I dont send files the request goes through.
I have read almost every github issue on this matter, switched to axios, tried multiple solutions and no luck. Does anyone know what the problem can be?
I tried to make a post request using fetch and it works on iOS but not on android.
I was expecting to work on both OS.`

Getting Network Error when trying to send Image to pre-signed URL in React Native

In my react native project I need to be able to send Images using axios to an API. For that I have the following function:
export function SetImage(image, id, token)
{
const formData = new FormData();
formData.append('file',{
uri: image.uri,
type: image.type,
})
return axios({
method: 'PUT',
url: axios.defaults.baseURL + "/api/SetImage/"+ID,
headers: {
'Content-Type': 'multipart/form-data' ,
'Authorization': 'Bearer: '+token,
},
data: formData
})
}
Image is the return Object I got from ImagePicker.launchImageLibraryAsync function which looks something like this:
{
"cancelled": false,
"height": 2048,
"type": "image",
"uri": "file:///data/user/0/host.exp.exponent/cache/<PathtoSomewhere>/ImagePicker/1d408e33-b54a-4189-
ac66-bd86ec11069a.jpg",
"width": 946,
}
However when I try to use the function I get the following error, that doesn't tell me anything:
Network Error
at node_modules\axios\lib\core\createError.js:16:14 in createError
at node_modules\axios\lib\adapters\xhr.js:84:13 in handleError
- ... 9 more stack frames from framework internals
I recently have to add same functionality to my project (upload image trough a pre-signed URL). This one is the ones that works for me:
const uploadImage = async ({ method, url, file }: any) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.open(method, url);
xhr.setRequestHeader('Content-Type', file.type);
xhr.onload = () => {
if (xhr.status !== 200) {
reject(
new Error(
`Request failed. Status: ${xhr.status}. Content: ${xhr.responseText
}`,
),
);
}
resolve(xhr.responseText);
};
xhr.send(file);
});
};
// image === image inside local phone
export const uploadImageToUrl = async ({ image, url }: any) => {
await uploadImage({
method: 'PUT', url, file: {
uri: image.uri,
type: image.type,
}
});
return { url };
};
To upload an image, you just need to call it like:
uploadImageToUrl({ url: your-upload-url, image: your-image-object-from-image-picker })
Note: pass the whole image object to the function (not just the uri)
Also add this line if necessary:
xhr.setRequestHeader('Authorization', 'Bearer ' + jwtoken);

How to upload photos with React Native

node v10.14.1
npm v6.4.1
strapi v3.0.0#13.0.1
I'm trying to upload a picture taken with a "PhotoUpload" component to Strapi.
Despite various tests, I get an error 500 from the server.
Insert_Files_Into_DataBase = () => {
const formdata = new FormData();
formdata.append("files:", this.state.image1); //Base64
this.setState(
{
ActivityIndicator_Loading: true
},
() => {
fetch("" + NETWORK.SERVER_IP + ":1337/upload", {
method: "POST",
headers: {
"Content-Type": "multipart/form-data",
Authorization: "Bearer " + this.props.userToken.jwt
},
body: formdata
})
.then(response => response.json())
.then(responseJsonFromServer => {
alert(responseJsonFromServer + "Image1 OK!");
this.setState({ ActivityIndicator_Loading: false });
})
.catch(error => {
console.error(error);
this.setState({ ActivityIndicator_Loading: false });
});
}
);
};
My "PhotoUpload" component allows me to retrieve the Base64 from the image. But it doesn't seem to work.
With Postman, everything works correctly
Are you doing this on the iOS simulator? I find uploading only works for me on a real iOS device.
In your code above, you are appending files: (with extra colon (:)). I think, you should append just files in the FormData() as:
formdata.append("files", this.state.image1); //Base64
This might be the case you are getting 500. If not also, you should append files instead of files:.
If this solves your problem, don't forget to hit upvote. :)
I found a first mistake!
I had simply forgotten the "HTTP://" in the address of my server.
Now, the server sends me back "true" but the image is not actually uploaded

React Native fetch throws error when posting multipart/form-data

This is how I tried to POST an image as multipart/form-data to server.
var photo = { uri: this.state.avatarSource,
type: 'multipart/form-data',
name: 'photo.jpg', };
let formdata = new FormData();
formdata.append('attachment',photo);
fetch(url,
{ method: "POST",
headers: { 'Content-Type': 'multipart/form-data' },
body: formdata
}).then((response) => response.json())
.catch((error) => { alert("ERROR " + error) })
.then((responseData) => { alert("Succes "+ responseData) }).done();
But it shows an error : Expected dynamic type string but had type
object
After 2 days, trying so many things I made the code working with some modifications.
RNFetchBlob.fetch('POST', url, {
'Content-Type': 'multipart/form-data',
}, [
{ name: 'file', filename: 'photo.jpg', type: 'image/png', data: RNFetchBlob.wrap(src) }
]) .then((resp) => {
console.log(resp.text());
}).catch((err) => {
console.log(err);
});
As mentioned in the docs formData.append(name, value, filename);
The value field in it accepts USVString or Blob, since you're passing an object to it therefore it throws an error.
You need to convert your image to blob, append and upload it.
If you've got the base64 of the image, then you can convert it to a blob directly using the fetch api
fetch(base64URL)
.then(res => res.blob())
.then(blob => console.log(blob))
Otherwise you may checkout RN-fetch-blob, their multipart/ formData example.
I slightly modified the solution given by #unknown123. And it worked for me.
Here is the solution.
First, install npm package rn-fetch-blob
import RNFetchBlob from 'rn-fetch-blob';
RNFetchBlob.fetch('PUT', url, {'Content-Type': 'multipart/form-data'},
Platform.OS === 'ios' ? RNFetchBlob.wrap(filePath) :
`RNFetchBlob-${filePath}`)
Please note, in my case, I had different file paths for IOS and Android devices. We handle it in different ways using rn-fetch-blob
Sample filePath variable data for
IOS device -
"/Users/Niveditha/Library/Developer/CoreSimulator/Devices/B41EB910-F22B-4236-8286-E6BA3EA75C70/data/Containers/Data/Application/B88777C6-6B10-4095-AB67-BB11E045C1DE/tmp/react-native-image-crop-picker/img.jpg"
Android device -
"file:///storage/emulated/0/Android/data/com.uploadcameraroll/files/Pictures/img.jpg"

React Native IOS application can not upload image through Express+ multer server

React Native IOS application, want to upload image; from device.
RN 0.39.2
Client:
const formData = new FormData()
formData.append('files', file)
formData.append('type', 'image')
fetch(API_HOST+UPLOAD_AVATAR,{
method:'post',
headers: {'Content-Type':'multipart/form-data;boundary=6ff46e0b6b5148d984f148b6542e5a5d','Authorization': 'Bearer'+' '+token},
body: formData
})
.then(response=>response.json())
.then(data=>{
//console.log(data)
//Alert.alert(data)
})
.catch(error=>{
console.log(error)
})
Server :
var multer = require('multer');
var upload = multer();
router.post('/user', ensureAuthenticated, upload.any(), function (req, res) {
console.log(req.body);
console.log(req.files);
})
Error:
server req.body and req.files are empty.
Then I try to use RNFetchBlob.
RNFetchBlob.fetch('POST', API_HOST+UPLOAD_AVATAR, {
'Content-Type':'multipart/form-data;boundary=6ff46e0b6b5148d984f148b6542e5a5d'
'Authorization' : 'Bearer'+' '+token
}, formData)
.then((resp) => {
}).catch((err) => {
// ...
})
then error change to
NSMutableDictionary cannot be converted to NSString.
And req.body is {}, req.files is undefined
I assume you found a solution to this, if yes, could you share it?.
In any case, for the RNFetchBlob issue, I used to get the same error and I solved by changing FormData to an array. Like this:
const body = [{
name: 'data',
data: JSON.stringify(whateverData)
}, {
name: 'file',
data: filePath,
}];
…
RNFetchBlob.fetch('POST', apiEndpoint, headers, body);
Hope that helps.