FastAPI 教程翻译 – 用户指南 19 请求文件

FastAPI 教程翻译 - 用户指南 19 请求文件
FastAPI Tutorial - User Guide - Request Files

You can define files to be uploaded by the client using File.

您可以使用 File 定义客户端上传的文件。

Info

信息

To receive uploaded files, first install python-multipart.

要接收上传的文件,请先安装 python-multipart

E.g. pip install python-multipart.

例如:pip install python-multipart

This is because uploaded files are sent as “form data”.

这是因为上载的文件会作为『表单数据』发送。

Import File

导入File

Import File and UploadFile from fastapi:

fastapi 导入 FileUploadFile

1
2
3
4
5
6
7
8
9
10
11
12
13
from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

Define File parameters

定义 File 参数

Create file parameters the same way you would for Body or Form:

创建文件参数的方式与创建 BodyForm 的方式相同:

1
2
3
4
5
6
7
8
9
10
11
12
13
from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

Info

信息

File is a class that inherits directly from Form.

File 是直接从 Form 继承的类。

But remember that when you import Query, Path, File and others from fastapi, those are actually functions that return special classes.

但是请记住,当您从 fastapi 中导入 QueryPathFile 和其他文件时,这些实际上是返回特殊类的函数。

Tip

提示

To declare File bodies, you need to use File, because otherwise the parameters would be interpreted as query parameters or body (JSON) parameters.

要声明文件主体,您需要使用 File,否则参数将被解释为查询参数或主体(JSON)参数。

The files will be uploaded as “form data”.

这些文件将作为『表单数据』上传。

If you declare the type of your path operation function parameter as bytes, FastAPI will read the file for you and you will receive the contents as bytes.

如果您将路径操作函数参数的类型声明为 bytes,则 FastAPI 将为您读取文件,并且您将以 bytes 形式接收内容。

Have in mind that this means that the whole contents will be stored in memory. This will work well for small files.

请记住,这意味着全部内容将存储在内存中。这对于小文件将非常有效。

But there are several cases in where you might benefit from using UploadFile.

但是在某些情况下,您可以从使用 UploadFile 中受益。

File parameters with UploadFile

UploadFile 类型的 File 参数

Define a File parameter with a type of UploadFile:

定义类型为 UploadFileFile 参数:

1
2
3
4
5
6
7
8
9
10
11
12
13
from fastapi import FastAPI, File, UploadFile

app = FastAPI()


@app.post("/files/")
async def create_file(file: bytes = File(...)):
    return {"file_size": len(file)}


@app.post("/uploadfile/")
async def create_upload_file(file: UploadFile = File(...)):
    return {"filename": file.filename}

Using UploadFile has several advantages over bytes:

bytes 相比,使用 UploadFile 有几个优点:

  • It uses a “spooled” file:

    使用『假脱机』文件:

    • A file stored in memory up to a maximum size limit, and after passing this limit it will be stored in disk.

      存储在内存中的文件大小有上限,超过此限制后,文件将存储在磁盘中。

  • This means that it will work well for large files like images, videos, large binaries, etc. without consuming all the memory.

    这意味着它可以很好地用于大型文件,例如图像、视频、大型二进制文件等,而不会占用所有内存。

  • You can get metadata from the uploaded file.

    您可以从上传的文件中获取元数据。

  • It has a file-like async interface.

    它具有 file-like 的 async 接口。

  • It exposes an actual Python SpooledTemporaryFile object that you can pass directly to other libraries that expect a file-like object.

    它公开了一个实际的 Python SpooledTemporaryFile 对象,您可以将其直接传递给需要类似文件对象的其他库。

UploadFile

UploadFile has the following attributes:

UploadFile 具有以下属性:

  • filename: A str with the original file name that was uploaded (e.g. myimage.jpg).

    带有上载原始文件名的 str(例如 myimage.jpg)。

  • content_type: A str with the content type (MIME type / media type) (e.g. image/jpeg).

    具有内容类型(MIME 类型 / 媒体类型)(例如 image/jpeg)的 str

  • file: A SpooledTemporaryFile (a file-like object). This is the actual Python file that you can pass directly to other functions or libraries that expect a “file-like” object.

    一个 SpooledTemporaryFile 对象(一个 file-like 对象)。这是实际的 Python 文件,您可以将其直接传递给需要『类文件』对象的其他函数或库。

UploadFile has the following async methods. They all call the corresponding file methods underneath (using the internal SpooledTemporaryFile).

UploadFile 具有以下 async 方法。它们都调用下面的相应文件方法(使用内部的 SpooledTemporaryFile)。

  • write(data): Writes data (str or bytes) to the file.

    datastrbytes)写入文件。

  • read(size): Reads size (int) bytes/characters of the file.

    从文件中读取 sizeint)的字节 / 字符。

  • seek(offset): Goes to the byte position offset (int) in the file.

    转到文件中的 offsetint)字节位置。

    • E.g., await myfile.seek(0) would go to the start of the file.

      例如:await myfile.seek(0) 将转到文件的开头。

    • This is especially useful if you run await myfile.read() once and then need to read the contents again.

      如果您运行了一次 await myfile.read() 然后需要再次读取内容,则此功能特别有用。

  • close(): Closes the file.

    关闭文件。

As all these methods are async methods, you need to “await” them.

由于所有这些方法都是 async 方法,因此您需要『等待』它们。

For example, inside of an async path operation function you can get the contents with:

例如:在 async 路径操作函数内部,您可以通过以下方式获取内容:

1
contents = await myfile.read()

If you are inside of a normal def path operation function, you can access the UploadFile.file directly, for example:

如果您在常规的 def 路径操作函数中,则可以直接访问 UploadFile.file,例如:

1
contents = myfile.file.read()

async Technical Details

async 技术细节

When you use the async methods, FastAPI runs the file methods in a threadpool and awaits for them.

当您使用 async 方法时,FastAPI 在线程池中运行文件方法并等待它们。

Starlette Technical Details

Starlette 技术细节

FastAPI’s UploadFile inherits directly from Starlette’s UploadFile, but adds some necessary parts to make it compatible with Pydantic and the other parts of FastAPI.

FastAPIUploadFile 直接继承自 StarletteUploadFile,但添加了一些必要的部分以使其与 PydanticFastAPI 的其他部分兼容。

What is “Form Data”

什么是『表单数据』

The way HTML forms (``) sends the data to the server normally uses a “special” encoding for that data, it’s different from JSON.

HTML 表单将数据发送到服务器的方式通常对该数据使用『特殊』编码,这与 JSON 不同。

FastAPI will make sure to read that data from the right place instead of JSON.

FastAPI 将确保从正确的位置而不是 JSON 读取数据。

Technical Details

技术细节

Data from forms is normally encoded using the “media type” application/x-www-form-urlencoded when it doesn’t include files.

表单中的数据不包含文件时,通常使用『媒体类型』application/x-www-form-urlencoded 进行编码。

But when the form includes files, it is encoded as multipart/form-data. If you use File, FastAPI will know it has to get the files from the correct part of the body.

但是,当表单包含文件时,它将被编码为 multipart/form-data。如果使用 FileFastAPI 将知道它必须从主体的正确部位获取文件。

If you want to read more about these encodings and form fields, head to the MDN web docs for POST.

如果您想了解有关这些编码和表单字段的更多信息,请转到 用于POST的MDN Web文档。

Warning

警告

You can declare multiple File and Form parameters in a path operation, but you can’t also declare Body fields that you expect to receive as JSON, as the request will have the body encoded using multipart/form-data instead of application/json.

您可以在路径操作中声明多个 FileForm 参数,但不能声明希望以 JSON 形式接收的 Body 字段,因为请求的主体将使用 multipart/form-data 而不是 application/json

This is not a limitation of FastAPI, it’s part of the HTTP protocol.

这不是 FastAPI 的限制,它是 HTTP 协议的一部分。

Multiple file uploads

多个文件上传

It’s possible to upload several files at the same time.

可以同时上传多个文件。

They would be associated to the same “form field” sent using “form data”.

它们将与使用『表单数据』发送的同一『表单字段』相关联。

To use that, declare a List of bytes or UploadFile:

要使用它,声明一个 bytesUploadFileList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
from typing import List

from fastapi import FastAPI, File, UploadFile
from fastapi.responses import HTMLResponse

app = FastAPI()


@app.post("/files/")
async def create_files(files: List[bytes] = File(...)):
    return {"file_sizes": [len(file) for file in files]}


@app.post("/uploadfiles/")
async def create_upload_files(files: List[UploadFile] = File(...)):
    return {"filenames": [file.filename for file in files]}


@app.get("/")
async def main():
    content = """
<body>
<form action="/files/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
<form action="/uploadfiles/" enctype="multipart/form-data" method="post">
<input name="files" type="file" multiple>
<input type="submit">
</form>
</body>
    """
    return HTMLResponse(content=content)

You will receive, as declared, a list of bytes or UploadFiles.

您将收到声明的 bytesUploadFilelist

Note

注意

Notice that, as of 2019-04-14, Swagger UI doesn’t support multiple file uploads in the same form field. For more information, check #4276 and #3641.

请注意,自 2019-04-14 起,Swagger UI 不支持在同一表单字段中上传多个文件。有关更多信息,请检查 #4276 和 #3641。

Nevertheless, FastAPI is already compatible with it, using the standard OpenAPI.

尽管如此,FastAPI 已经使用标准的 OpenAPI 与之兼容。

So, whenever Swagger UI supports multi-file uploads, or any other tools that supports OpenAPI, they will be compatible with FastAPI.

因此,只要 Swagger UI 支持多文件上传或任何其他支持 OpenAPI 的工具,它们都将与 FastAPI 兼容。

Technical Details

技术细节

You could also use from starlette.responses import HTMLResponse.

您也可以使用 from starlette.responses import HTMLResponse

FastAPI provides the same starlette.responses as fastapi.responses just as a convenience for you, the developer. But most of the available responses come directly from Starlette.

FastAPI 提供与 starlette.responses 相同的 fastapi.responses,只是为开发人员提供方便。但是大多数可用的响应直接来自 Starlette。

Recap

回顾

Use File to declare files to be uploaded as input parameters (as form data).

使用 File 声明要上传的文件作为输入参数(作为表单数据)。