Comment publier un fichier depuis un formulaire avec Axios

130

En utilisant du HTML brut lorsque je publie un fichier sur un serveur flask en utilisant ce qui suit, je peux accéder aux fichiers à partir de la requête flask globale:

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

En flacon:

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

Quand j'essaye de faire la même chose avec Axios, la requête globale du flacon est vide:

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

Si j'utilise la même fonction uploadFile ci-dessus mais que je supprime les en-têtes json de la méthode axios.post, j'obtiens dans la clé de forme de mon objet de demande de flacon une liste csv de valeurs de chaîne (le fichier est un .csv).

Comment puis-je envoyer un objet fichier via axios?

Don Smythe
la source
@Niklesh oui coupage et collage de faute de frappe, je l'ai corrigé ci-dessus, inclut des guillemets dans le code.
Don Smythe
avez-vous essayé v-on:change="uploadFile"avec inputau lieu de formtag?
Niklesh Raut
@Niklesh J'obtiens le même résultat - les données envoyées sous forme de chaîne et récupérées par request.form et non par request.files dans le flacon.
Don Smythe

Réponses:

273

Ajoutez le fichier à un formDataobjet et définissez l'en- Content-Typetête sur 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
la source
1
Après avoir publié les fichiers. Avons-nous besoin d'y accéder à partir d'une requête HTTP ou devons-nous y accéder à partir de paramètres côté serveur.
Parth Patel
@ParthPatel: J'utilise $_FILESpour obtenir des fichiers côté serveur car j'utilise PHP
Niklesh Raut
7
Merci pour ce post, mais je ne vois toujours pas pourquoi nous en avons besoin FormData. Selon la documentation d'axios, les deux Fileet FormDatasont traités comme un navigateur uniquement , de sorte que les deux manières peuvent être vues de manière égale ( github.com/axios/axios#request-config )
Hiroki
Impressionnant ! J'envoyais "data: {data: formData}" qui générait l'erreur 412. Cela fonctionnait avecdata:formData
Aseem
3
ATTENTION: l'extrait fonctionne tel quel lorsqu'il est exécuté dans le contexte d'un navigateur. Pour fonctionner dans node.js, il faut passer les en-têtes calculés par formData.getHeaders()Ceci est un problème connu avec axios; voir par exemplehttps://github.com/axios/axios/issues/789
mjv
13

Exemple d'application utilisant Vue. Nécessite un serveur backend s'exécutant sur localhost pour traiter la demande:

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
la source
puis-je vous demander de jeter un œil à une question liée à axios ici: stackoverflow.com/questions/59470085/... ?
Istiaque Ahmed
5

Cela fonctionne pour moi, j'espère aider à quelqu'un.

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
la source
en utilisant Nuxt - cela a finalement fonctionné pour moi. la suppression headers: { 'Content-Type': 'multipart/form-data' }était le seul moyen d'envoyer le message après avoir obtenu une réponse du serveur à partir d'options. Je fais probablement quelque chose de mal, mais cela fonctionne et je le laisse tranquille lol
Jeff Bluemel
C'est génial! Je n'aurais jamais pensé que vous pourriez envoyer le formulaire complet. Merci!
Dara Java