J. Bones
J. Bones

Reputation: 489

How do you send images to node js with Axios?

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

Answers (6)

Irfan wani
Irfan wani

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

Cmontalvo80
Cmontalvo80

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:

  1. I included some headers as a configuration object after the data object passed into the axios.post call. The content type you're including here is the key. You're submitting a multipart/form-data content type.
  2. Within that Content type header, I also added a boundary, which is derived from the data object you created earlier.
  3. The 'file' used here is just the file object I passed into my action. It's just the name I used for my object, you can use anything you want here.

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

Yangshun Tay
Yangshun Tay

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

Andath
Andath

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

Volodymyr Synytskyi
Volodymyr Synytskyi

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

Harkirat Saluja
Harkirat Saluja

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

Related Questions