Post to /upload from react native - react-native

I'm trying to upload a picture to strapi from react native.
async function uploadPicture(uri) {
var data = new FormData();
data.append('files', {
uri: uri.replace('file://', ''),
name: uri,
type: 'image/jpg'
});
// Create the config object for the POST
// You typically have an OAuth2 token that you use for authentication
const config = {
method: 'POST',
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data;'
},
body: data
};
const fetchPromise = fetch('http://<host>:1337/upload', config)
console.log(fetchPromise)
return await fetchPromise
}
I get a 200 status code but no new picture is listed on the uploads page.

Oh! I figured it out using simple-http-upload-server to test the uploads. The problem was that I was setting the name of the file to be the uri. This would probably cause an error on strapi when creating the file on the server folder. It should return an error code nonetheless.

Related

multipart/form-data request failing in react-native

I get the following error when I set the 'Content-Type' as 'multipart/form-data' in react-native.
Below is my code -
const formData = new FormData();
formData.append('org_id', org_id);
formData.append('ans', userAns);
formData.append('remark', userRemark);
formData.append('img', userImg);
files.forEach(file => {
formData.append('files', {
name: file.fileName,
type: file.type,
uri: file.uri,
});
});
const resp = await multiPartInstance({
method: 'PUT',
url: `${apiBaseUrl}/installation/${Iid}/answer/${qid}`,
data: formData,
});
return Promise.resolve(true);
I am using axios for calling apis. multiPartInstance is an axios instance -
const multiPartAccessToken = async (config: AxiosRequestConfig) => {
config.headers = {
Accept: 'application/json',
access_token: useTokenStore.getState().accessToken,
'Content-Type': 'multipart/form-data;',
};
config.timeout = 30000;
return config;
};
I've tried the above with fetch also but I keep getting the same error. The strangest part is that this request hits the server, server sends a response too but I get this error react-native side. I've noticed if I don't use FormData I don't get any error. But I need to use FormData as I have to upload image files.
Environment Details -
Windows version 21H2 (OS Build 22000.376)
react-native 0.66.3
react 17.0.2
axios ^0.24.0
react-native-image-picker ^4.3.0 (used for selecting images)
Flipper version 0.99.0
I've tried the solutions posted on below forums but they didn't work for me.
request formData to API, gets “Network Error” in axios while uploading image
https://github.com/facebook/react-native/issues/24039
https://github.com/facebook/react-native/issues/28551
I am as follow and works perfectly:
const oFormData = new FormData();
images.map((val, index) => {
oFormData.append("image", {
uri: val.uri,
type: val.type,
name: val.fileName
});
});
return axios.post(postServiceUrl, oFormData);
Somehow react-native-blob-util doesn't give this error. I modified my code as below -
import ReactNativeBlobUtil from 'react-native-blob-util';
const fileData = files.map(file => {
return {
name: 'files',
data: String(file.base64),
filename: file.fileName,
};
});
try {
const resp = await ReactNativeBlobUtil.fetch(
'PUT',
`${apiBaseUrl}/installation/${Iid}/answer/${qid}`,
{
access_token: useTokenStore.getState().accessToken,
'Content-Type': 'multipart/form-data',
},
[
...fileData,
// elements without property `filename` will be sent as plain text
{name: 'org_id', data: String(org_id)},
{name: 'ans', data: String(userAns)},
{name: 'remark', data: String(userRemark)},
{name: 'img', data: String(userImg)},
],
);

react native getting network error when sending files with axios

i'm using api platform to create end Point to handle images upload.
My api require a file type to make a post request.
This is an example of post request using post man :
I want to handle sending images with axios using react native.
I created a post request like this :
this.setState({
avatarSource: source,
});
console.log(this.state.avatarSource.uri);
const data = new FormData();
data.append('file', {
uri: this.state.avatarSource.uri,
// show full image path in my device
// file:///storage/emulated/0/Pictures/image-c40b64fc-6d74-46a7-9016-191aff3740dd.jpg
});
axios
.post(`${API.URL}/media_objects`, data, {
headers: {
'Content-Type': 'multipart/form-data',
},
})
.then((resp) => console.log(resp))
.catch((err) => console.log(err.message));
}
});
I'm sending the full path of image in my phone to the api but i got "Network Error"
I fixed the problem by commenting this line in ReactNativeFlipper.java :
NetworkFlipperPlugin networkFlipperPlugin = new NetworkFlipperPlugin();
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
#Override
public void apply(OkHttpClient.Builder builder) {
// builder.addNetworkInterceptor(new FlipperOkhttpInterceptor(networkFlipperPlugin)); // add comment here and build android
}
});
client.addPlugin(networkFlipperPlugin);
client.start();

Android: Network Request Failed when trying to upload image with fetch

I'm trying to upload an image from storage to a restful API but I keep getting Network Request Failed on Android (which means the request doesn't even go through), haven't checked on iOS because I don't need that part yet. API is already working and has been tested with Postman.
The React Native code is:
body.append('vehicles',{
resource_id: 2,
resource: 'vehicles',
cat_file_id: fileId,
active: 1,
vehicles: photo, //<- photo value below
name: 'vehicles',
type: 'image/jpeg'
})
fetch(`${BASE_URL}/files`, {
method: 'POST',
headers: {
'Content-Type': 'multipart/form-data',
Accept: "*/*",
Authorization: 'Bearer '+auth
},
body: body
}).then(response => response.json())
.then(response => {
console.log('IMAGE RESPONSE', response)
})
.catch(error => console.log('ERROR', error))
The photo value looks like file:///storage/emulated/0/DCIM/...
The response:
ERROR TypeError: Network request failed
at XMLHttpRequest.xhr.onerror (fetch.umd.js:473)
at XMLHttpRequest.dispatchEvent (event-target-shim.js:818)
at XMLHttpRequest.setReadyState (XMLHttpRequest.js:574)
at XMLHttpRequest.__didCompleteResponse (XMLHttpRequest.js:388)
at XMLHttpRequest.js:501
at RCTDeviceEventEmitter.emit (EventEmitter.js:189)
at MessageQueue.__callFunction (MessageQueue.js:436)
at MessageQueue.js:111
at MessageQueue.__guard (MessageQueue.js:384)
at MessageQueue.callFunctionReturnFlushedQueue (MessageQueue.js:110)
On Postman the request looks something like this:
Already tried:
Removing Accept header
Changing Accept value to 'application/json'
Removing file:// from the image url
Added android:usesCleartextTraffic="true" to the manifest
Already checked:
No values are null or undefined
There is a working internet connection, all other network requests on the app are working fine
The Auth is correct
React Native version is 0.61.5
I found one missing line in your code let formData = new FormData();. but not sure is that the exact issue here.
By the way here is a sample working code from one of my project, and I customized it with your context.
Add your authentication
replace ImageURI with image path and URL_SAVE_IMAGE endpoint url
const newImage = {
resource_id: 2,
resource: 'vehicles',
cat_file_id: 1,
active: 1,
vehicles: ImageURI,
name: "my_photo.jpg",
type: "image/jpg",
};
let formData = new FormData();
formData.append("vehicles", newImage);
return fetch(URL_SAVE_IMAGE, {
method: 'POST',
headers: {
"Content-Type": "multipart/form-data"
},
body: formData
}).then(response => response.json());
it should work!
What is your fetch(${BASE_URL}/files` backend server .. This usually happens when trying to connect to the backend api on the localhost machine.. Even if you use the IP address of the localhost, it still persists, so it is better to use online server for testing or just use ngrok(https://ngrok.com/) to serve your backend localhost via internet.
in gradle.properties change the flipper version to 0.47.0
try with Xhr, it's working as expected!
const URL = "ANY_SERVER/upload/image"
const xhr = new XMLHttpRequest();
xhr.open('POST', url); // the address really doesnt matter the error occures before the network request is even made.
const data = new FormData();
data.append('image', { uri: image.path, name: 'image.jpg', type: 'image/jpeg' });
xhr.send(data);
xhr.onreadystatechange = e => {
if (xhr.readyState !== 4) {
return;
}
if (xhr.status === 200) {
console.log('success', xhr.responseText);
} else {
console.log('error', xhr.responseText);
}
};
Nothing worked for me except using the Expo FileSystem uploadAsync
uploadImage = async ({ imageUri } }) => FileSystem.uploadAsync(
apiUrl,
imageUri,
{
headers: {
// Auth etc
},
uploadType: FileSystem.FileSystemUploadType.MULTIPART,
fieldName: 'files',
mimeType: 'image/png',
});
Note - imageUri in format of file:///mypath/to/image.png
Happy days!

Image upload in React Native (Expo), using fetch results in 400 error

I have been struggling with image upload for days.
I’m using formdata like this:
let formData = new FormData();
formData.append('file', {
uri: uri,
name: `name`,
type: `image/jpeg`,
});
uri on iOS is something like asset-library://asset/path on Android it is like content://media/external/images/media/25377.
let options = {
method: 'POST',
body: formData,
headers: {
Accept: 'application/json',
'Authorization': 'Bearer ' + token,
},
};
let response = await fetch("https://myserverurl", options)
I tried every trick reading the image as blob, removing content-type, other libraries like axios, etc…
No matter what I always get back a 400 bad file format error.
Is there something I’m missing with formdata?
(On the backend we use ASP.NET)
We have had a similar issue and were able to solve the issue the following way.
We are using a NodeJS backend (with multer) to handle the file uploads.
Expo - Mobile App Code
// extract the filetype
let fileType = uri.substring(uri.lastIndexOf(".") + 1);
let formData = new FormData();
formData.append("photo", {
uri,
name: `photo.${fileType}`,
type: `image/${fileType}`
});
let options = {
method: "POST",
body: formData,
headers: {
Accept: "application/json",
"Content-Type": "multipart/form-data"
}
};
We are executing the request with fetch(apiUrl, options).
The uri is the local file path (full URI e.g., file:///...) of the photo in our case and apiUrl is the endpoint of the server-side.
I think the issue might be with the type and format of uri in formdata. Have you tried to use the uri returned by the image picker?

React Native upload image to server failed in android

i am using the following code to but i keep getting in android, which was showing "Network request failed", but it was no problem if i not append photo file data in the FormData. Why I am getting this problem?
const data = new FormData();
data.append("name", "testName"); // you can append anyone.
data.append("photo", {
uri: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADMAAAAzCAYAAAA6oTAqAAAAEXRFWHRTb2Z0d2FyZQBwbmdjcnVzaEB1SfMAAABQSURBVGje7dSxCQBACARB+2/ab8BEeQNhFi6WSYzYLYudDQYGBgYGBgYGBgYGBgYGBgZmcvDqYGBgmhivGQYGBgYGBgYGBgYGBgYGBgbmQw+P/eMrC5UTVAAAAABJRU5ErkJggg==',
type: 'image/png', // or photo.type
name: 'testPhotoName.png'
});
fetch('https://ptsv2.com/t/1gfl7-1544694996/post', {
method: "post",
body: data
}).then(res => {
console.log(res);
});