ChatGPT解决这个技术问题 Extra ChatGPT

How to post a file from a form with Axios

Using raw HTML when I post a file to a flask server using the following I can access files from the flask request global:

<form id="uploadForm" action='upload_file' role="form" method="post" enctype=multipart/form-data>
    <input type="file" id="file" name="file">
    <input type=submit value=Upload>
</form>

In flask:

def post(self):
    if 'file' in request.files:
        ....

When I try to do the same with Axios the flask request global is empty:

<form id="uploadForm" enctype="multipart/form-data" v-on:change="uploadFile">
<input type="file" id="file" name="file">
</form>

uploadFile: function (event) {
    const file = event.target.files[0]
    axios.post('upload_file', file, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
    })
}

If I use the same uploadFile function above but remove the headers json from the axios.post method I get in the form key of my flask request object a csv list of string values (file is a .csv).

How can I get a file object sent via axios?

@Niklesh yes typo cutting and pasting, I fixed it above, includes double quotes in code.
did you tried v-on:change="uploadFile" with input instead of form tag ?
@Niklesh I get same result - data sent as string and picked up by request.form not request.files in flask.

d
davidism

Add the file to a formData object, and set the Content-Type header to multipart/form-data.

var formData = new FormData();
var imagefile = document.querySelector('#file');
formData.append("image", imagefile.files[0]);
axios.post('upload_file', formData, {
    headers: {
      'Content-Type': 'multipart/form-data'
    }
})

After posting the files. Do we need to access them from HTTP request or need to access them from parameters on server side.
Thanks for this post, but I still don't see why we need FormData. According to axios's doc, both File and FormData are treated as Browser only, so both ways can be seen equally (github.com/axios/axios#request-config)
Awesome ! I was sending 'data:{ data:formData}' which was generating error 412. It worked with data:formData
ATTENTION: the snippet works as-is when run in the context of a browser. To run in node.js, one needs to pass the headers computed by formData.getHeaders() This is a known issue with axios; see for e.g. https://github.com/axios/axios/issues/789
About the comment by @Hiroki on File vs. FormData: correct me if I'm wrong, but I believe File can be used only if you're uploading a single file and not including any other payload data in the request (like in the answer), but FormData is what you'll have to use if you want to submit a collection of data (that is, a form with several fields) in addition to the file(s) (which I suspect is more often the case in real applications).
x
xlm

Sample application using Vue. Requires a backend server running on localhost to process the request:

var app = new Vue({
  el: "#app",
  data: {
    file: ''
  },
  methods: {
    submitFile() {
      let formData = new FormData();
      formData.append('file', this.file);
      console.log('>> formData >> ', formData);

      // You should have a server side REST API 
      axios.post('http://localhost:8080/restapi/fileupload',
          formData, {
            headers: {
              'Content-Type': 'multipart/form-data'
            }
          }
        ).then(function () {
          console.log('SUCCESS!!');
        })
        .catch(function () {
          console.log('FAILURE!!');
        });
    },
    handleFileUpload() {
      this.file = this.$refs.file.files[0];
      console.log('>>>> 1st element in files array >>>> ', this.file);
    }
  }
});

https://codepen.io/pmarimuthu/pen/MqqaOE


E
Emma

If you don't want to use a FormData object (e.g. your API takes specific content-type signatures and multipart/formdata isn't one of them) then you can do this instead:

uploadFile: function (event) {
    const file = event.target.files[0]
    axios.post('upload_file', file, {
        headers: {
          'Content-Type': file.type
        }
    })
}

If you use PUT to upload file then you may use application/octet-stream as Content-Type. If you upload into Amazon S3 storage using multipart/formdata as Content-Type it will make your files (images, pdfs, documents) into text files with http header added on top. This will damage the content of the uploaded file. So use application/octet-stream when uploading binary files with PUT methods.
O
OCornejo

This works for me, I hope helps to someone.

var frm = $('#frm');
let formData = new FormData(frm[0]);
axios.post('your-url', formData)
    .then(res => {
        console.log({res});
    }).catch(err => {
        console.error({err});
    });

using Nuxt - this finally worked for me. removing headers: { 'Content-Type': 'multipart/form-data' } was the only way it would actually send the post after getting a server response from options. I am probably doing something wrong, but it is working and I'm leaving it alone lol
@JeffBluemel Content-Type headers are set automagically. You are supposed to have those undefined.
J
Jafar Karuthedath

Sharing my experience with React & HTML input

Define input field

<input type="file" onChange={onChange} accept ="image/*"/>

Define onChange listener

const onChange = (e) => {
  let url = "https://<server-url>/api/upload";
  let file = e.target.files[0];
  uploadFile(url, file);
};

const uploadFile = (url, file) => {
  let formData = new FormData();
  formData.append("file", file);
  axios.post(url, formData, {
      headers: {
        "Content-Type": "multipart/form-data",
      },
    }).then((response) => {
      fnSuccess(response);
    }).catch((error) => {
      fnFail(error);
    });
};
const fnSuccess = (response) => {
  //Add success handling
};

const fnFail = (error) => {
  //Add failed handling
};

Y
Yarh

How to post file using an object in memory (like a JSON object):

import axios from 'axios';
import * as FormData  from 'form-data'

async function sendData(jsonData){
    // const payload = JSON.stringify({ hello: 'world'});
    const payload = JSON.stringify(jsonData);
    const bufferObject = Buffer.from(payload, 'utf-8');
    const file = new FormData();

    file.append('upload_file', bufferObject, "b.json");

    const response = await axios.post(
        lovelyURL,
        file,
        headers: file.getHeaders()
    ).toPromise();


    console.log(response?.data);
}

I
IAmdeGroot

For me the error was the actual parameter name in my controller... Took me a while to figure out, perhaps it will help someone. Im using Next.js / .Net 6

Client:

export const test = async (event: any) => {
    const token = useAuthStore.getState().token;
    console.log(event + 'the event')
    if (token) {
        const formData = new FormData();
        formData.append("img", event);
        const res = await axios.post(baseUrl + '/products/uploadproductimage', formData, {
            headers: {
                'Authorization': `bearer ${token}`
            }
        })
        return res
    }
    return null
}

Server:

 [HttpPost("uploadproductimage")]
        public async Task<ActionResult> UploadProductImage([FromForm] IFormFile image)
        {
            return Ok();
        }

Error here because server is expecting param "image" and not "img:

formData.append("img", event);

 public async Task<ActionResult> UploadProductImage([FromForm] IFormFile image)