So veröffentlichen Sie eine Datei aus einem Formular mit Axios

127

Wenn ich eine Datei mit Roh-HTML auf einem Flask-Server poste, kann ich über die Flask-Anfrage global auf Dateien zugreifen:

<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 der Flasche:

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

Wenn ich versuche, dasselbe mit Axios zu tun, ist die globale Flaschenanforderung leer:

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

Wenn ich die gleiche Funktion uploadFile wie oben verwende, aber die Header json aus der axios.post-Methode entferne, erhalte ich im Formularschlüssel meines Flask-Anforderungsobjekts eine CSV-Liste mit Zeichenfolgenwerten (Datei ist eine CSV-Datei).

Wie kann ich ein Dateiobjekt über Axios senden lassen?

Don Smythe
quelle
@Niklesh ja Tippfehler ausschneiden und einfügen, ich habe es oben behoben, enthält doppelte Anführungszeichen im Code.
Don Smythe
hast du es v-on:change="uploadFile"mit inputstatt formtag versucht ?
Niklesh Raut
@Niklesh Ich erhalte das gleiche Ergebnis - Daten werden als Zeichenfolge gesendet und von request.form not request.files in flask aufgenommen.
Don Smythe

Antworten:

266

Fügen Sie die Datei einem formDataObjekt hinzu und setzen Sie den Content-TypeHeader auf 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
quelle
1
Nach dem Posten der Dateien. Müssen wir über eine HTTP-Anfrage auf sie zugreifen oder müssen wir über Parameter auf der Serverseite darauf zugreifen?
Parth Patel
@ParthPatel: Ich verwende $_FILES, um Dateien auf der Serverseite
abzurufen,
7
Danke für diesen Beitrag, aber ich verstehe immer noch nicht, warum wir brauchen FormData. Laut axios 'Dokument werden beide Fileund FormDatanur als Browser behandelt , sodass beide Möglichkeiten gleichermaßen angezeigt werden können ( github.com/axios/axios#request-config )
Hiroki
Genial ! Ich habe 'data: {data: formData}' gesendet, was den Fehler 412 erzeugte. Es funktionierte mitdata:formData
Aseem
3
ACHTUNG: Das Snippet funktioniert unverändert, wenn es im Kontext eines Browsers ausgeführt wird. Um in node.js ausgeführt zu werden, müssen die von berechneten Header übergeben werden. formData.getHeaders()Dies ist ein bekanntes Problem bei axios. siehe zBhttps://github.com/axios/axios/issues/789
mjv
12

Beispielanwendung mit Vue. Erfordert einen Backend-Server, der auf localhost ausgeführt wird, um die Anforderung zu verarbeiten:

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
quelle
Darf ich Sie bitten, sich hier eine Frage zu Axios anzusehen : stackoverflow.com/questions/59470085/… ?
Istiaque Ahmed
5

Das funktioniert bei mir, ich hoffe es hilft jemandem.

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
quelle
mit Nuxt - das hat endlich bei mir funktioniert. Das Entfernen headers: { 'Content-Type': 'multipart/form-data' }war die einzige Möglichkeit, den Beitrag tatsächlich zu senden, nachdem eine Serverantwort von den Optionen erhalten wurde. Ich mache wahrscheinlich etwas falsch, aber es funktioniert und ich
lasse
Das ist brilliant! Ich hätte nie gedacht, dass Sie das ganze Formular senden könnten. Vielen Dank!
Dara Java