Jak wysłać plik z formularza w Axios

129

Używając surowego kodu HTML, gdy wysyłam plik na serwer flask, mogę uzyskać dostęp do plików z globalnego żądania flask:

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

W kolbie:

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

Kiedy próbuję zrobić to samo z Axios, globalne żądanie kolby jest puste:

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

Jeśli używam tej samej funkcji uploadFile powyżej, ale usuwam nagłówki json z metody axios.post, otrzymuję w kluczu formularza mojego obiektu żądania kolby listę csv wartości ciągów (plik jest .csv).

Jak mogę uzyskać obiekt pliku wysłany przez axios?

Don Smythe
źródło
@Niklesh tak, wycinanie i wklejanie literówek, poprawiłem to powyżej, zawiera podwójne cudzysłowy w kodzie.
Don Smythe,
pan próbował v-on:change="uploadFile"ze inputzamiast formtagu?
Niklesh Raut
@Niklesh Otrzymuję ten sam wynik - dane wysyłane jako łańcuch i odbierane przez request.form, a nie request.files w flbie.
Don Smythe,

Odpowiedzi:

270

Dodaj plik do formDataobiektu i ustaw Content-Typenagłówek na 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
źródło
1
Po wysłaniu plików. Czy musimy uzyskać do nich dostęp z żądania HTTP, czy też musimy uzyskać do nich dostęp z parametrów po stronie serwera.
Parth Patel
@ParthPatel: Używam $_FILESdo pobierania plików po stronie serwera, ponieważ używam PHP
Niklesh Raut
7
Dzięki za ten post, ale nadal nie rozumiem, dlaczego potrzebujemy FormData. Zgodnie z dokumentem Axiosa oba Filei FormDatasą traktowane tylko jako przeglądarka , więc oba sposoby można zobaczyć tak samo ( github.com/axios/axios#request-config )
Hiroki
Niesamowite ! Wysyłałem „dane: {data: formData}”, co generowało błąd 412. data:formData
Zadziałało
3
UWAGA: fragment kodu działa bez zmian, gdy jest uruchamiany w kontekście przeglądarki. Aby uruchomić w node.js, trzeba przekazać nagłówki obliczone przez formData.getHeaders()To jest znany problem z axios; patrz np.https://github.com/axios/axios/issues/789
mjv
13

Przykładowa aplikacja wykorzystująca Vue. Wymaga serwera zaplecza działającego na hoście lokalnym do przetworzenia żądania:

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
źródło
czy mogę prosić o przyjrzenie się pytaniu związanemu z Axios: stackoverflow.com/questions/59470085/… ?
Istiaque Ahmed
5

To działa dla mnie, mam nadzieję, że komuś pomoże.

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
źródło
używając Nuxt - to w końcu zadziałało. usunięcie headers: { 'Content-Type': 'multipart/form-data' }było jedynym sposobem, w jaki faktycznie wysłał post po otrzymaniu odpowiedzi serwera z opcji. Pewnie coś robię źle, ale działa i zostawiam to w spokoju lol
Jeff Bluemel
To jest genialne! Nigdy bym nie pomyślał, że możesz wysłać cały formularz. Dzięki!
Dara Java