329

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> <script> function uploadFile(event) { const file = event.target.files[0] axios.post('upload_file', file, { headers: { 'Content-Type': 'multipart/form-data' } }) } </script> 

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?

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

10 Answers 10

602

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' } }) 
Sign up to request clarification or add additional context in comments.

8 Comments

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).
|
33

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

Comments

31

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 } }) } 

1 Comment

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.
21

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 }; 

Comments

15

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}); }); 

2 Comments

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.
7

this is my way:

var formData = new FormData(formElement); // formData.append("image", imgFile.files[0]); const res = await axios.post( "link-handle", formData, { headers: { "Content-Type": "multipart/form-data", }, } ); 

Comments

1

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); } 

Comments

1

There is an issue with Axios version 0.25.0 > to 0.27.2 where FormData object in a PUT request is not handled correctly if you have appended more than one field but is fine with one field containing a file, POST works fine.

Also Axios 0.25.0+ automatically sets the correct headers so there is no need to specify Content-Type.

Comments

0

We have NEW Axios documentation here:

The simpliest way is:

await axios.postForm(url, document.querySelector('#fileInput').files) 

With onUploadProgress in config:

const config = { onUploadProgress: function(progressEvent) { var percentCompleted = Math.round((progressEvent.loaded * 100) / progressEvent.total) console.log(percentCompleted) } } await axios.postForm(url, document.querySelector('#fileInput').files, config) 

Backend will receive a files[] multipart-form field

Comments

-2

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) 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.