javascript FastAPI -使用Axios上传多个文件会引发错误请求错误

rjee0c15  于 2023-02-07  发布在  Java
关注(0)|答案(2)|浏览(204)

客户代码:

!<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title></title>
    <script src="https://cdn.jsdelivr.net/npm/axios/dist/axios.min.js"></script>
</head>

<form id="uploadForm" role="form" method="post" enctype=multipart/form-data>
    <input type="file" id="file" name="file" multiple>
    <input type=button value=Upload onclick="uploadFile()">
</form>

<script type="text/javascript">
function uploadFile() {
   var formData = new FormData();
    var imagefile = document.querySelector('#file');
    formData.append("images", imagefile.files);
    axios.post('http://127.0.0.1:8000/upload', formData, {
        headers: {
          'Content-Type': 'multipart/form-data'
        }
    })
}
</script>
</body>
</html>

服务器代码:

from fastapi import FastAPI, File, UploadFile, FastAPI
from typing import Optional, List
from fastapi.responses import FileResponse, HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware

...

def save_file(filename, data):
    with open(filename, 'wb') as f:
        f.write(data)
        print('file saved')

@app.post("/upload")
async def upload(files: List[UploadFile] = File(...)):
    print(files)
    for file in files:
        contents = await file.read()
        save_file(file.filename, contents)
        print('file received')

    return {"Uploaded Filenames": [file.filename for file in files]}

出现以下错误:

←[32mINFO←[0m:     127.0.0.1:10406 - "←[1mPOST /upload HTTP/1.1←[0m" ←[31m400 Bad Request←[0m

我已经尝试通过表单操作上传一个文件,所有工作正常,但我需要上传两个文件。

az31mfrm

az31mfrm1#

首先,当上传文件或表单数据时,应该使用在端点/路由中定义的相同表单键。在您的情况下,该键是files。因此,在客户端应该使用该键而不是images
其次,上载多个文件的方法是循环遍历文件数组(即代码中的imagefile.files),并将每个文件添加到FormData对象。
第三,错误似乎是由于Axios的0.27.1版本中的一些bug/更改而发生的。这里是最新的related issue on GitHub。使用cdnjs here的最新版本,即0.27.2解决了这个问题。
或者,您可以使用Fetch API,类似于this answer(您可以使用与下面Axios示例相同的方式添加文件列表)。在Fetch API中,当将文件上传到服务器时,您不应该显式设置请求上的Content-Type头,如here所述。

工作示例(使用Axios)

<!DOCTYPE html>
<html>
   <head>
      <meta charset="utf-8">
      <meta name="viewport" content="width=device-width, initial-scale=1">
      <title>Upload Files</title>
      <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.27.2/axios.min.js"></script>   
   </head>
   <body>
      <input type="file" id="fileInput" multiple><br>
      <input type="button" value="Upload" onclick="uploadFile()">
      <script type="text/javascript">
         function uploadFile() {
             var fileInput = document.querySelector('#fileInput'); 
         
             if (fileInput.files[0]) {
                var formData = new FormData();
                for (const file of fileInput.files)
                    formData.append('files', file);

                 axios({
                         method: 'post',
                         url: '/upload',
                         data: formData,
                         headers: {
                             'Accept': 'application/json',
                             'Content-Type': 'multipart/form-data'
                         }
                     })
                    .then(response => {
                        console.log(response);
                    })
                    .catch(error => {
                        console.error(error);
                    });
             }
         }
      </script>
   </body>
</html>
ih99xse1

ih99xse12#

从Axios v 0.27.2开始,您可以轻松地完成此操作:

axios
    .postForm("https://httpbin.org/post", document.querySelector("#fileInput").files)

所有文件将使用files[]密钥提交。
更详细的示例:

axios.postForm("https://httpbin.org/post", {
      "myField": "foo"
      "myJson{}": {x:1, y: 'bar'}, 
      "files[]": document.querySelector("#fileInput").files
    })

相关问题