React-Native image upload - reactjs

Is it possible to upload file (images) to server with react-native using FormData? Tried to use it like this:
var data = new FormData();
data.append('file', file);
console.log(JSON.stringify(data));
var id = 5;
fetch('http://192.168.1.104:3000/app/complaint/uploadFile?id='+id,{
method:'POST',
body: data,
headers: {
'Accept': 'application/json',
'Content-Type': 'multipart/form-data;',
},
});
For React, FormData works as expected but for React-Native not working.
I have also tried (used in react - working)
const data = fetch('http://192.168.1.104:3000/app/complaint/uploadFile?id='+id, {
credentials: "same-origin",
method:'POST',
body: dataval,
timeout: 1000000000,
});
But nothing works,
In the back-end server, I am upload using
var d = require('domain').create()
d.run(function safelyUpload () {
var file=req.file('file').upload({dirname: path.resolve(sails.config.appPath, folder),
}, function whenDone(err, uploadedFiles) {
if (err) return res.serverError(err);
else{
sails.log.debug('Complaint File data : ' +util.inspect(uploadedFiles, {showHidden: true,depth: null}));
}
});
});
Is there any other ways

Here is example to upload image using Fetch API
const photo = {
uri: user.profilePicture,
type: 'image/jpeg',
name: 'photo.jpg',
};
const form = new FormData();
form.append("ProfilePicture", photo);
fetch(
URL,
{
body: form,
method: "PUT",
headers: {
'Content-Type': 'multipart/form-data',
'Authorization': 'Bearer ' + user.token
}
}
).then((response) => response.json())
.catch((error) => {
alert("ERROR " + error)
})
.then((responseData) => {
alert("Succes "+ responseData)
}).done();
Credits https://stackoverflow.com/a/36649457/5315786

Related

Send images to backend using ReactJS

I want to make a post request to backend with all form data.
Uploading the images i get an array with data:
const normFile = e => {
const getFileList = e.fileList.map( i => i.originFileObj);
console.log('Upload event:', getFileList);
fetch('https:///uploadapi', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ images: getFileList })
})
.then(async response => {
const data = await response.json();
console.log(data, 'res data')
})
.catch(error => {
console.error('There was an error!', error);
});
if (Array.isArray(e)) {
return e;
}
return e && e.fileList;
};
Above is my code where i use Ant Design uploader.
But how to delete the File text before each object?
You have to use multipart/form-data header
Let's say you have an input
<input type="file" onChange={uploadFile}/>
And logical part:
uploadFile = (e) => {
const formData = new FormData();
formData.append('name_your_file', e.target.files[0])
fetch('https:///uploadapi', {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
body: formData
})
}

AXIOS get request failed 400 React Native

I am trying to make an axios get request to this endpoint, but I am keep getting this error " [Error: Request failed with status code 400]".
clikk = () => {
console.log('saasdasdl');
var user = 'reflect-user';
var pass = 'user1Pass';
let dta = JSON.stringify({
username: 'test.admin',
password: 'password',
emailAddress: 'test#gmai.com',
});
const headers = {
'Content-Type': 'application/json',
Authorization: 'Basic ctesmtVmbGVjdC11c2VyOnVzZXIxUGFzcw==',
'Access-Control-Allow-Origin': '*',
accept: 'application/json',
};
// var bytes = utf8.encode(user + ':' + pass);
// var authorizationBasic = base64.encode(bytes);
axios({
method: 'get',
url: 'http://IpOfServer:8080/api/v1/user/getUser?all=true',
headers: headers,
data: qs.parse({
username: 'test.admin',
password: 'password',
emailAddress: 'test#gmai.com',
}),
})
.then((res) => {
//const nameList = res.data;
//this.setState({nameList});
console.log(res);
})
.catch((error) => console.log(error));
};
However same request is working in POSTMAN so API may not be involved ish? I've also tried to AXIOS example provided by POSTMAN but I am getting the same error.
var data = JSON.stringify({"username":"test.admin","password":"password","emailAddress":"test6#gmai.com"});
var config = {
method: 'get',
url: 'http://IpOfServer:8080/api/v1/user/getUser?all=true',
headers: {
'Authorization': 'Basic cmVmbGVjdC11c2VyOnVzZXIxUGFzcw==',
'Content-Type': 'application/json'
},
data : data
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
Thank you.

react native post form data with object and file in it using axios

so i want to upload
object as data
and file as Note
to api using axios
uploadToServer= () => {
const file =this.state.photo
let data2 ={sale_id:1,
note_type_id:4,
description:"test",
note_content_item:" hi from broker hub"
}
let data = new FormData()
data.append('data[sale_id]', '1')
data.append('data[note_type_id]', '4')
data.append('data[description]', "test")
data.append('data[note_content_item]', "test")
console.log(data)
axios({
url: api',
method: 'POST',
data: data,
headers: {
'Content-Type' : 'multipart/form-data',
'Authorization':'Basic YnJva2VyOmJyb2tlcl8xMjM='
}
})
.then(resp => console.log(resp.data.response))
.catch(error => console.error(error));
}
first i am trying with data without Note i can do it in postman
but with my code i got error
message: "Can not save file"
response_code: 10
i got this error only if i change the key from data to something else
when you are using react-native you don't need "form-data" package. Because react native polyfills standard FormData api and exports it as global.
second problem is axios converts form data automatically to string, so you need to use transformRequest config on request to override it.
import { AxiosRequestConfig } from "axios";
const FormData = global.FormData;
const axiosInstance = axios.create({
baseURL: 'example.com', // use with scheme
timeout: 30000,
headers: {
"X-Platform": 'iOS',
"X-App-Build-Number": '1.0.0',
},
});
const formData = new FormData();
formData.append("userId", "123456");
formData.append("file", {
uri: "/dev/sda/abc.png",
type: "image/png",
name: "abc.png",
});
const config: AxiosRequestConfig = {
method: "post",
url: "/process/start",
responseType: "json",
headers: {
'Content-Type': 'multipart/form-data',
// if backend supports u can use gzip request encoding
// "Content-Encoding": "gzip",
},
transformRequest: (data, headers) => {
// !!! override data to return formData
// since axios converts that to string
return formData;
},
onUploadProgress: (progressEvent) => {
// use upload data, since it's an upload progress
// iOS: {"isTrusted": false, "lengthComputable": true, "loaded": 123, "total": 98902}
},
data: formData,
};
// send post request and get response
const response = await axiosInstance.request(config);
You are not building FormData correctly, Try this:
let data = {sale_id:1,
note_type_id:4,
description:"test",
note_content_item:" hi from broker hub"
}
const formData = new FormData();
formData.append('data', JSON.stringify(data));
formData.append('Note', {
uri: "file://" //Your Image File Path
type: 'image/jpeg',
name: "imagename.jpg",
});
axios({
url : api,
method : 'POST',
data : formData,
headers: {
Accept: 'application/json',
'Content-Type': 'multipart/form-data',
'Authorization':'Basic YnJva2VyOmJyb2tlcl8xMjM='
}
})
.then(function (response) {
console.log("response :", response);
})
.catch(function (error) {
console.log("error from image :");
})
This might help you:
import {Platform} from 'react-native';
import axios from 'axios';
const upload = async readPath => {
console.log('path', readPath);
const URL = 'your-url';
const headers = {
headers: {
'Content-Type': 'multipart/form-data',
Accept: 'application/json',
Authorization: `Bearer ${projectSecret}`,
},
};
const formData = new FormData();
const file = {
uri:
Platform.OS === 'android' ? `file:///${readPath}` : readPath,
type: 'text/plain',
name: name,
};
formData.append('file', file);
await axios
.post(URL, formData, headers, {
timeout: 3000,
})
.then(async response => {
console.log(response.data);
})
.catch(error => {
console.log('error : ', error);
});
};

How to use post method in react native?

constructor(props) {
super(props);
this.state = {text: this.props.navigation.state.params.text,
name:this.props.navigation.state.params.name};
}
manage = () => {
Alert.alert('done')
Actions.reset('mainScreen');
fetch("http://ip/api/confirm", {
method: "POST",
headers: {
Accept: "application/json",
"Content-Type": "application/json"
},
body: JSON.stringify({
name: this.props.navigation.state.params.name,
text:this.props.navigation.state.params.text
})
})
.then(response => response.json())
.catch(error => {
console.error(error);
});
}
i want to do this
when i press in button go to manage function
and post the text and the name to my api i dont know how can i pass them
its give me this error :
network request failed
any help please
I recommend you to use axios to make network requests.
Installing:
npm i -S axios
Performing a POST request:
import axios from 'axios';
axios({
url: 'http://ip/api/confirm',
method: 'post',
data: {
name: this.props.navigation.state.params.name,
text: this.props.navigation.state.params.text,
},
headers: {
Accept: 'application/json',
'Content-Type': 'application/json',
}
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
var resp = await manage(this.props.session.userId,this.props.session.ApiKey,"hi","hello");
if (resp.status == 200){
var respBody = await resp.json();
console.log('Fetch Todo response '+respBody);
}
API in separate file
export async function manage(userId,ApiKey,query,query1) {
var url ="http://www.example.com/getdata";
const params = {
search:query,
searches:query1
};
var formBody = [];
for (const property in params) {
const encodedKey = encodeURIComponent(property);
const encodedValue = encodeURIComponent(params[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
const requestOptions = {
'method': 'POST',
'headers': {
'Content-Type': 'application/x-www-form-urlencoded'
// 'Content-Type': 'application/json'
},
'body': formBody
};
requestOptions.headers["userid"] = userId
requestOptions.headers["apikey"] = ApiKey
try {
var resp = await fetch(url, requestOptions);
return resp;
}
catch (err) {
console.log("Request Failed: " + err);
return err;
}
}

axios post request to send form data

axios POST request is hitting the url on the controller but setting null values to my POJO class, when I go through developer tools in chrome, the payload contains data. What am I doing wrong?
Axios POST Request:
var body = {
userName: 'Fred',
userEmail: 'Flintstone#gmail.com'
}
axios({
method: 'post',
url: '/addUser',
data: body
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
Browser Response:
If I set headers as:
headers:{
Content-Type:'multipart/form-data'
}
The request throws the error
Error in posting multipart/form-data. Content-Type header is missing boundary
If I make the same request in postman it's working fine and sets values to my POJO class.
Can anyone explain how to set boundary or how can I send form data using axios.
You can post axios data by using FormData() like:
var bodyFormData = new FormData();
And then add the fields to the form you want to send:
bodyFormData.append('userName', 'Fred');
If you are uploading images, you may want to use .append
bodyFormData.append('image', imageFile);
And then you can use axios post method (You can amend it accordingly)
axios({
method: "post",
url: "myurl",
data: bodyFormData,
headers: { "Content-Type": "multipart/form-data" },
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
Related GitHub issue:
Can't get a .post with 'Content-Type': 'multipart/form-data' to work # axios/axios
In my case I had to add the boundary to the header like the following:
const form = new FormData();
form.append(item.name, fs.createReadStream(pathToFile));
const response = await axios({
method: 'post',
url: 'http://www.yourserver.com/upload',
data: form,
headers: {
'Content-Type': `multipart/form-data; boundary=${form._boundary}`,
},
});
This solution is also useful if you're working with React Native.
Check out querystring.
You can use it as follows:
var querystring = require('querystring');
axios.post('http://something.com/', querystring.stringify({ foo: 'bar' }));
Upload (multiple) binary files
Node.js
Things become complicated when you want to post files via multipart/form-data, especially multiple binary files. Below is a working example:
const FormData = require('form-data')
const fs = require('fs')
const path = require('path')
const formData = new FormData()
formData.append('files[]', JSON.stringify({ to: [{ phoneNumber: process.env.RINGCENTRAL_RECEIVER }] }), 'test.json')
formData.append('files[]', fs.createReadStream(path.join(__dirname, 'test.png')), 'test.png')
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData, {
headers: formData.getHeaders()
})
Instead of headers: {'Content-Type': 'multipart/form-data' } I prefer headers: formData.getHeaders()
I use async and await above, you can change them to plain Promise statements if you don't like them
In order to add your own headers, you just headers: { ...yourHeaders, ...formData.getHeaders() }
Newly added content below:
Browser
Browser's FormData is different from the NPM package 'form-data'. The following code works for me in browser:
HTML:
<input type="file" id="image" accept="image/png"/>
JavaScript:
const formData = new FormData()
// add a non-binary file
formData.append('files[]', new Blob(['{"hello": "world"}'], { type: 'application/json' }), 'request.json')
// add a binary file
const element = document.getElementById('image')
const file = element.files[0]
formData.append('files[]', file, file.name)
await rc.post('/restapi/v1.0/account/~/extension/~/fax', formData)
2020 ES6 way of doing
Having the form in html I binded in data like so:
DATA:
form: {
name: 'Joan Cap de porc',
email: 'fake#email.com',
phone: 2323,
query: 'cap d\ou'
file: null,
legal: false
},
onSubmit:
async submitForm() {
const formData = new FormData()
Object.keys(this.form).forEach((key) => {
formData.append(key, this.form[key])
})
try {
await this.$axios.post('/ajax/contact/contact-us', formData)
this.$emit('formSent')
} catch (err) {
this.errors.push('form_error')
}
}
Using application/x-www-form-urlencoded format in axios
By default, axios serializes JavaScript objects to JSON. To send data
in the application/x-www-form-urlencoded format instead, you can use
one of the following options.
Browser
In a browser, you can use the URLSearchParams API as follows:
const params = new URLSearchParams();
params.append('param1', 'value1');
params.append('param2', 'value2');
axios.post('/foo', params);
Note that URLSearchParams is not supported by all browsers (see caniuse.com), but there is a polyfill available (make sure to polyfill the global environment).
Alternatively, you can encode data using the qs library:
const qs = require('qs');
axios.post('/foo', qs.stringify({ 'bar': 123 }));
Or in another way (ES6),
import qs from 'qs';
const data = { 'bar': 123 };
const options = {
method: 'POST',
headers: { 'content-type': 'application/x-www-form-urlencoded' },
data: qs.stringify(data),
url, };
axios(options);
Even More straightforward:
axios.post('/addUser',{
userName: 'Fred',
userEmail: 'Flintstone#gmail.com'
})
.then(function (response) {
console.log(response);
})
.catch(function (error) {
console.log(error);
});
import axios from "axios";
import qs from "qs";
const url = "https://yourapplicationbaseurl/api/user/authenticate";
let data = {
Email: "testuser#gmail.com",
Password: "Admin#123"
};
let options = {
method: "POST",
headers: { "content-type": "application/x-www-form-urlencoded" },
data: qs.stringify(data),
url
};
axios(options)
.then(res => {
console.log("yeh we have", res.data);
})
.catch(er => {
console.log("no data sorry ", er);
});
};
I had the similar issues when using FormData with axios to make calls on https://apps.dev.microsoft.com service and it error-red out with "The request body must contain the following parameter: 'grant_type'"
After reformatting the data from
{
grant_type: 'client_credentials',
id: '123',
secret: '456789'
}
to
"grant_type=client_credentials&id=123&secret=456789"
and the following code worked:
const config: AxiosRequestConfig = {
method: 'post',
url: https://apps.dev.microsoft.com/auth,
data: 'grant_type=client_credentials&id=123&secret=456789',
headers: {
'Content-Type': 'application/x-www-form-urlencoded',
}
};
axios(config)
.then(function (response) {
console.log(JSON.stringify(response.data));
})
.catch(function (error) {
console.log(error);
});
i needed to calculate the content length aswell
const formHeaders = form.getHeaders();
formHeaders["Content-Length"] = form.getLengthSync()
const config = {headers: formHeaders}
return axios.post(url, form, config)
.then(res => {
console.log(`form uploaded`)
})
A boundary (which is used, by the server, to parse the payload) is set when the request is sent. You can't obtain the boundary before making the request. So, a better way to get this is using getBoundary() from your FormData.
var formData = new FormData();
formData.append('userName', 'Fred');
formData.append('file0', fileZero);
formData.append('file1', fileOne);
axios({
method: "post",
url: "myurl",
data: formData,
headers: {
'Content-Type': `multipart/form-data; ${formData.getBoundary()}`,
})
.then(function (response) {
//handle success
console.log(response);
})
.catch(function (response) {
//handle error
console.log(response);
});
I needed to upload many files at once using axios and I struggled for a while because of the FormData API:
// const instance = axios.create(config);
let fd = new FormData();
for (const img of images) { // images is an array of File Object
fd.append('images', img, img.name); // multiple upload
}
const response = await instance({
method: 'post',
url: '/upload/',
data: fd
})
I did NOT specify the content-type: multipart/form-data header!
The above method worked for me but since it was something I needed often, I used a basic method for flat object. Note, I was also using Vue and not REACT
packageData: (data) => {
const form = new FormData()
for ( const key in data ) {
form.append(key, data[key]);
}
return form
}
Which worked for me until I ran into more complex data structures with nested objects and files which then let to the following
packageData: (obj, form, namespace) => {
for(const property in obj) {
// if form is passed in through recursion assign otherwise create new
const formData = form || new FormData()
let formKey
if(obj.hasOwnProperty(property)) {
if(namespace) {
formKey = namespace + '[' + property + ']';
} else {
formKey = property;
}
// if the property is an object, but not a File, use recursion.
if(typeof obj[property] === 'object' && !(obj[property] instanceof File)) {
packageData(obj[property], formData, property);
} else {
// if it's a string or a File
formData.append(formKey, obj[property]);
}
}
}
return formData;
}
For me it worked using axios, typescript and form-data(v4.0.0):
import FormData from "form-data";
import axios from "axios";
async function login() {
var data = new FormData();
data.append("User", "asdf");
const return = await axios.post(
"https://ptsv2.com/t/1q9gx-1652805776/post", data,
{ headers: data.getHeaders() }
);
console.log(return);
}
This should work well when needing to POST x-www-form-urlencoded data using axios from a NodeJS environment. You may need to add an Authorization header to the config.headers object if the endpoint requires authentication.
const config = {
headers: {
accept: 'application/json',
'cache-control': 'no-cache',
'content-type': 'application/x-www-form-urlencoded'
}
const params = new URLSearchParams({key1: value1, key2: value2});
return axios
.post(url, params.toString(), config)
.then((response) => {
return response.data;
})
.catch((error) => console.error(error));
In my case, the problem was that the format of the FormData append operation needed the additional "options" parameter filling in to define the filename thus:
var formData = new FormData();
formData.append(fieldName, fileBuffer, {filename: originalName});
I'm seeing a lot of complaints that axios is broken, but in fact the root cause is not using form-data properly. My versions are:
"axios": "^0.21.1",
"form-data": "^3.0.0",
On the receiving end I am processing this with multer, and the original problem was that the file array was not being filled - I was always getting back a request with no files parsed from the stream.
In addition, it was necessary to pass the form-data header set in the axios request:
const response = await axios.post(getBackendURL() + '/api/Documents/' + userId + '/createDocument', formData, {
headers: formData.getHeaders()
});
My entire function looks like this:
async function uploadDocumentTransaction(userId, fileBuffer, fieldName, originalName) {
var formData = new FormData();
formData.append(fieldName, fileBuffer, {filename: originalName});
try {
const response = await axios.post(
getBackendURL() + '/api/Documents/' + userId + '/createDocument',
formData,
{
headers: formData.getHeaders()
}
);
return response;
} catch (err) {
// error handling
}
}
The value of the "fieldName" is not significant, unless you have some receiving end processing that needs it.
https://www.npmjs.com/package/axios
Its Working
// "content-type": "application/x-www-form-urlencoded",
// commit this
import axios from 'axios';
let requestData = {
username : "abc#gmail.cm",
password: "123456"
};
const url = "Your Url Paste Here";
let options = {
method: "POST",
headers: {
'Content-type': 'application/json; charset=UTF-8',
Authorization: 'Bearer ' + "your token Paste Here",
},
data: JSON.stringify(requestData),
url
};
axios(options)
.then(response => {
console.log("K_____ res :- ", response);
console.log("K_____ res status:- ", response.status);
})
.catch(error => {
console.log("K_____ error :- ", error);
});
fetch request
fetch(url, {
method: 'POST',
body: JSON.stringify(requestPayload),
headers: {
'Content-type': 'application/json; charset=UTF-8',
Authorization: 'Bearer ' + token,
},
})
// .then((response) => response.json()) . // commit out this part if response body is empty
.then((json) => {
console.log("response :- ", json);
}).catch((error)=>{
console.log("Api call error ", error.message);
alert(error.message);
});
transformRequest: [
function(data, headers) {
headers["Content-Type"] = "application/json";
return JSON.stringify(data);
}
]
try this, it works

Resources