【问题标题】:FastAPI - Upload files with Axios - Bad RequestFastAPI - 使用 Axios 上传文件 - 错误请求
【发布时间】:2022-07-24 15:32:38
【问题描述】:

客户端代码:

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

我尝试通过表单操作上传单个文件,一切正常,但我需要上传两个文件。

【问题讨论】:

  • 您在 JS 中使用 images 作为表单键,但在您的 FastAPI 定义中使用 files。 400 错误是否有包含更多详细信息的正文?它是否与常规表单和&lt;input type="file" name="images (or files)" multiple&gt;一起正常工作?

标签: python http axios fastapi


【解决方案1】:

首先,上传文件或表单数据时,应使用在其端点/路由中定义的相同表单键。在你的情况下,那是files。因此,在客户端,您应该使用该密钥而不是 images

其次,上传多个文件的方法是遍历文件数组(即代码中的imagefile.files)并将每个文件添加到FormData对象中。

第三,错误似乎是由于0.27.1 版本的 Axios 中的一些错误/更改而发生的。这是最近的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">
      <title>Upload Files</title>
      <script type="text/javascript" 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>

【讨论】:

    【解决方案2】:

    从 Axios v 0.27.2 开始你可以do this easily:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-07-24
      • 2021-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-11-12
      • 2021-12-05
      相关资源
      最近更新 更多