Reputation: 489
Is there a way to send an array of images (or a single image) to node using axios?
The axios code I'm using(I'm using react js on the front end):
onFormSubmit(event){
event.preventDefault();
let payload = this.state;
console.log("in onFormSubmit!!! with state: ", this.state, "and payload: ", payload);
axios.post('/api/art', payload)
.then(function(response){
console.log('saved successfully')
});
The research I've done suggests that perhaps there isn't a supported way to send image files to node using axios, but this seems strange to me. Is there a way?
Upvotes: 40
Views: 161114
Reputation: 5075
All we need to upload an image to a backend is header multipart/form-data
, image details (uri
, name
, type
) and form-data.
import FormData from 'form-data'
const config = {
headers: {
'Content-Type': 'multipart/form-data'
}
}
const data = new FormData();
data.append('image', {
uri: image.uri,
name: image.uri.split('/').pop(), //split the uri at / and get the last element of the resulting array which actually is the name with the image extention (e.g, abc.jpg)
type: image.type // type needs to be modified. keep reading
})
Now here is an important point. Many times the type from the image details is not the complete type (like, it returns only 'image' but the actual type is 'image/jpeg') and this results in network error
.
Now to get the accurate type, we can use some third party package to do so.
E.g, we can use mime
.
import mime from 'mime'
type: mime.getType(image.uri)
Then at last, we just need to send the request.
axios.post('url', data, config)
.then(...)
.catch(...)
Not only images, but we can also upload videos with the exact same procedure.
Upvotes: 3
Reputation: 381
Here is the way I got this to work properly. I had to make use of an object called FormData. I used the import:
import FormData from 'form-data'
Of course before this import I had to run the npm install for it:
npm install --save form-data
Once I did all that, here is how I used it within my action:
let data = new FormData();
data.append('file', file, file.name);
return (dispatch) => {
axios.post(URL, data, {
headers: {
'accept': 'application/json',
'Accept-Language': 'en-US,en;q=0.8',
'Content-Type': `multipart/form-data; boundary=${data._boundary}`,
}
})
.then((response) => {
//handle success
}).catch((error) => {
//handle error
});
};}
The important pieces to note here are:
Hope this helps, this cleared up all of the issues I had with trying to submit an image to a backend (in my case a rest service - through a post call).
Upvotes: 38
Reputation: 53149
Yes you will have to set the content type in your axios request:
axios.put(url, imageFile, {
headers: {
'Content-Type': imageFile.type
}
});
where imageFile
is an HTML5 file object which should be an image in your case.
Upvotes: 18
Reputation: 22724
With HTML5 you can use FormData()
to construct a set of key/value pairs representing form fields and their values you want to send. In most cases, as in a user submitting a form, the method to use is FormData.set()
which can be manipulated in its 2 forms:
There are two versions of this method: a two and a three parameter version:
formData.set(name, value);
formData.set(name, value, filename);
Once you construct your data object, do not forget to specify the multipart content type header for your HTTP POST request so that you can send the file to your server.
Below is a summary of what I said:
onFormSubmit(event){
let formData = new FormData(); // instantiate it
// suppose you have your file ready
formData.set('file', yourFile);
// add some data you collected from the input fields
formData.set('data1', dataInputField1); // suppose you got dataInputField1 from your HTML5 form input
axios.post('/api/art', formData, {
headers: {
'content-type': 'multipart/form-data' // do not forget this
}})
}
Upvotes: 8
Reputation: 4055
Here is how I implemented it:
onFormSubmit(event){
var form = new FormData();
files.forEach(file => {
form.append(file.name, file);
});
form.append('foo', 'bar');
axios.post('/api/art', form)
});
On node js server make sure to use some middle-ware which handles multipart requests. I used multer.
Here are my results on the endpoint:
req.body - { foo: 'bar' }
req.files - {
'r1.jpg': {
fieldname: 'r1.jpg',
originalname: 'r1.jpg',
name: 'e2f4b9874fd7d6115b9f7440b9ead3a0.jpg',
encoding: '7bit',
mimetype: 'image/jpeg',
path: '/tmp/e2f4b9874fd7d6115b9f7440b9ead3a0.jpg',
extension: 'jpg',
size: 45641,
truncated: false,
buffer: null
}, ...
}
Upvotes: 14
Reputation: 8114
I would say instead of doing this manually you can use a library called react-dropzone for this . So basically what you need to do is :-
import React,{Component} from 'react';
import Dropzone from 'react-dropzone';
import request from 'superagent';
class DropZone extends Component{
onDrop(files){
var file = new FormData();
file.append('name',files[0])
var req=request
.post('http://localhost:8000/api/v0/image/')
.send(file);
req.end(function(err,response){
console.log("upload done!!!!!");
});
}
render(){
return(
<div>
<Dropzone onDrop={this.onDrop}>
<div>Try dropping some files here, or click to select files to upload.</div>
</Dropzone>
</div>
);
}
}
You can check here for git repo. I have implemented this in django but i dont think backend should be a problem, you can use node
Upvotes: 2