Axiosを使用してフォームからファイルを投稿する方法


128

以下を使用してフラスコサーバーにファイルを投稿するときに生のHTMLを使用すると、フラスコリクエストグローバルからファイルにアクセスできます。

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

フラスコ内:

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

Axiosで同じことを行おうとすると、フラスコリクエストグローバルが空になります。

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

上記と同じuploadFile関数を使用して、ヘッダーjsonをaxios.postメソッドから削除した場合、フラスコリクエストオブジェクトのフォームキーに文字列値のcsvリストを取得します(ファイルは.csv)。

どうすればaxios経由で送信されたファイルオブジェクトを取得できますか?


@Nikleshはい、タイプミスのカットアンドペーストで修正しました。コードに二重引用符が含まれています。
Don Smythe 2017年

タグの代わりに試しv-on:change="uploadFile"ましたか?inputform
Niklesh Raut 2017年

@Niklesh同じ結果が得られます-データは文字列として送信され、フラスコ内のrequest.filesではなくrequest.formによって取得されます。
Don Smythe 2017年

回答:


268

ファイルをformDataオブジェクトに追加し、Content-Typeヘッダーをに設定し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'
    }
})

1
ファイルを投稿した後。HTTPリクエストからアクセスする必要があるのか​​、それともサーバー側のパラメーターからアクセスする必要があるのか​​。
Parth Patel 2017

@ParthPatel:$_FILESPHP を使用しているので、サーバー側でファイルを取得するために使用しています
Niklesh Raut

7
この投稿に感謝しますが、なぜ必要なのかまだわかりませんFormData。axiosのドキュメントによれば、両方FileFormDataとして扱われる だけブラウザので、両方の方法は、(同等に見ることができるgithub.com/axios/axios#request-config
ヒロキ

驚くばかり !エラー412を生成していた 'data:{data:formData}'を送信していました。これは動作しましたdata:formData
Aseem

3
注意:スニペットは、ブラウザーのコンテキストで実行すると、そのまま機能します。node.jsで実行するにformData.getHeaders()は、これによって計算されたヘッダーを渡す必要があります。これは、axiosの既知の問題です。例については参照してくださいhttps://github.com/axios/axios/issues/789
mjv

13

Vueを使用したサンプルアプリケーション。リクエストを処理するには、localhostで実行されているバックエンドサーバーが必要です。

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


ここにaxios関連の質問を見てもらいますか: stackoverflow.com/questions/59470085/…
Istiaque Ahmed

5

これは私にとってはうまくいきます。

var frm = $('#frm');
let formData = new FormData(frm[0]);
axios.post('your-url', formData)
    .then(res => {
        console.log({res});
    }).catch(err => {
        console.error({err});
    });

Nuxtを使用して-これは最終的に私のために働いた。headers: { 'Content-Type': 'multipart/form-data' }オプションからサーバーからの応答を受け取った後に実際に投稿を送信する唯一の方法は、削除でした。私はおそらく何か悪いことをしていますが、それはうまくいき、私はそれを一人にしていますlol
ジェフブルーメル

これは素晴らしいです!フォーム全体を送信できるとは思いもしませんでした。ありがとう!
Dara Java
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.