Como postar um arquivo de um formulário com Axios

128

Usando HTML bruto ao postar um arquivo em um servidor flask, posso acessar arquivos da solicitação flask 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>

Em frasco:

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

Quando tento fazer o mesmo com o Axios, a solicitação de frasco global está vazia:

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

Se eu usar a mesma função uploadFile acima, mas remover os cabeçalhos json do método axios.post, obtenho na chave do formulário do meu objeto de solicitação de balão uma lista csv de valores de string (o arquivo é um .csv).

Como posso obter um objeto de arquivo enviado via axios?

Don Smythe
fonte
@Niklesh sim erro de digitação, recortar e colar, corrigi-lo acima, inclui aspas duplas no código.
Don Smythe
você tentou v-on:change="uploadFile"com em inputvez de formtag?
Niklesh Raut
@Niklesh, obtenho o mesmo resultado - dados enviados como string e coletados por request.form, não por request.files no frasco.
Don Smythe,

Respostas:

268

Adicione o arquivo a um formDataobjeto e defina o Content-Typecabeçalho como 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'
    }
})
Niklesh Raut
fonte
1
Depois de postar os arquivos. Precisamos acessá-los a partir de uma solicitação HTTP ou precisamos acessá-los a partir de parâmetros no lado do servidor.
Parth Patel
@ParthPatel: Estou usando $_FILESpara obter arquivos no lado do servidor, pois estou usando PHP
Niklesh Raut
7
Obrigado por esta postagem, mas ainda não vejo por que precisamos FormData. De acordo com o documento do axios, ambos Filee FormDatasão tratados apenas como navegador , então as duas formas podem ser vistas igualmente ( github.com/axios/axios#request-config )
Hiroki
Impressionante ! Eu estava enviando 'data: {data: formData}' que estava gerando o erro 412. Funcionou comdata:formData
Aseem
3
ATENÇÃO: o snippet funciona como está quando executado no contexto de um navegador. Para executar em node.js, é necessário passar os cabeçalhos calculados por formData.getHeaders()Este é um problema conhecido com axios; veja por exemplohttps://github.com/axios/axios/issues/789
mjv
13

Aplicação de amostra usando Vue. Requer um servidor de back-end em execução no host local para processar a solicitação:

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

maris
fonte
posso pedir que você dê uma olhada em uma questão relacionada a axios aqui: stackoverflow.com/questions/59470085/… ?
Istiaque Ahmed
5

Isso funciona para mim, espero que ajude alguém.

var frm = $('#frm');
let formData = new FormData(frm[0]);
axios.post('your-url', formData)
    .then(res => {
        console.log({res});
    }).catch(err => {
        console.error({err});
    });
OCornejo
fonte
usando o Nuxt - isso finalmente funcionou para mim. remover headers: { 'Content-Type': 'multipart/form-data' }era a única maneira de realmente enviar a postagem após obter uma resposta do servidor das opções. Provavelmente estou fazendo algo errado, mas está funcionando e estou deixando isso sozinho lol
Jeff Bluemel
Isto é brilhante! Nunca pensei que pudesse enviar o formulário completo. Obrigado!
Dara Java