I'm trying to send an image from react native to my server using fetch and it's working on ios but not android. i'm testing on physical devices. the error that is returned is a Network Error exception.
Also, I'm using fetch for all of my api calls, and all the POST requests where I'm sending just a JSON body are working fine, even on Android. It's just sending the image using fetch + formData that's not working on Android.
Some things I've tried are (mostly suggestions on other questions similar to this one)
- [commenting out flipper in MainApplication][1]: https://stackoverflow.com/a/61126831/2395829
- tried working with the
XMLHttpRequest
object directly - tried removing the headers in the post request
- added
android:usesCleartextTraffic="true"
to AndroidManifest.xml
I've spent a few hours on this but can't get it to work...
It's possible some of the changes I made to AndroidManifest didn't get synced. I ran npm run android
after changing file and it said the Gradle sync completed so I don't think that's too likely...
The code snippet below is where the formData object is created and the fetch request sent
const data = new FormData()
data.append('avatar', {
uri: res,
type: 'image/jpeg',
name: 'gravavatar',
uid: userData.id,
imagePos: idx,
})
fetch(global.BASE_URL + '/save_profile_image/' + userData.id + '/' + imagePos + '/no', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
// 'Access-Control-Allow-Origin': '*',
},
// make sure to serialize your JSON body
body: data
}).then(response => {
if (response.ok) {
// do stuff like setState
}
}).catch(err => {
console.log(err)
})
The entire function is below.
const _pickImage = async (idx) => {
try {
let result = null
try {
result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: false,
aspect: [4, 3],
quality: 0.05,
});
} catch (err) {
console.log('IMAGE FAILED')
console.log(err)
return;
}
if (!result.cancelled) {
let images = [...state.images];
images[idx] = result.uri
if (result.uri.slice(0, 4) == 'file') {
var xhr = new XMLHttpRequest();
xhr.open("GET", result.uri, true);
xhr.responseType = "blob";
xhr.onload = function(e) {
console.log(this.response);
var reader = new FileReader();
reader.onload = async function(event) {
var res = event.target.result;
var stringLength = res.length - 'data:image/png;base64,'.length;
var sizeInBytes = 4 * Math.ceil((stringLength / 3)) * 0.5624896334383812;
var sizeInKb = sizeInBytes / 1000;
// console.log(sizeInKb)
if (sizeInKb > 4999) {
alert('File is too large')
return;
}
const data = new FormData()
data.append('avatar', {
uri: res,
type: 'image/jpeg',
name: 'gravavatar',
uid: userData.id,
imagePos: idx,
})
fetch(global.BASE_URL + '/save_profile_image/' + userData.id + '/' + imagePos + '/no', {
method: 'post',
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data',
// 'Access-Control-Allow-Origin': '*',
},
// make sure to serialize your JSON body
body: data
}).then(response => {
if (response.ok) {
// do stuff like setState
}
}).catch(err => {
console.log(err)
})
}
var file = this.response;
reader.readAsDataURL(file)
};
xhr.send()
}
return;
}
} catch (E) {
console.log(E);
}
};
Help would be much appreciated. Thank you.