Arquivos de Requisição¶
🌐 Tradução por IA e humanos
Esta tradução foi feita por IA orientada por humanos. 🤝
Ela pode conter erros de interpretação do significado original ou soar pouco natural, etc. 🤖
Você pode melhorar esta tradução ajudando-nos a orientar melhor o LLM de IA.
Você pode definir arquivos para serem enviados pelo cliente usando File.
Nota
Para receber arquivos enviados, primeiro instale python-multipart.
Garanta que você criou um ambiente virtual, o ativou e então o instalou, por exemplo:
$ pipinstallpython-multipart
Isso é necessário, visto que os arquivos enviados são enviados como "dados de formulário".
Importe File¶
Importe File e UploadFile de fastapi:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: bytes = File()):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
Definir Parâmetros File¶
Crie parâmetros de arquivo da mesma forma que você faria para Body ou Form:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: bytes = File()):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
Nota
File é uma classe que herda diretamente de Form.
Mas lembre-se que quando você importa Query, Path, File e outros de fastapi, eles são, na verdade, funções que retornam classes especiais.
Dica
Para declarar corpos de arquivos, você precisa usar File, caso contrário, os parâmetros seriam interpretados como parâmetros de consulta ou parâmetros de corpo (JSON).
Os arquivos serão enviados como "dados de formulário".
Se você declarar o tipo do parâmetro da sua função de operação de rota como bytes, o FastAPI lerá o arquivo para você e você receberá o conteúdo como bytes.
Mantenha em mente que isso significa que todo o conteúdo será armazenado na memória. Isso funcionará bem para arquivos pequenos.
Mas há muitos casos em que você pode se beneficiar do uso de UploadFile.
Parâmetros de Arquivo com UploadFile¶
Defina um parâmetro de arquivo com um tipo de UploadFile:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: Annotated[bytes, File()]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: bytes = File()):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile):
return {"filename": file.filename}
Utilizar UploadFile tem várias vantagens sobre bytes:
- Você não precisa utilizar o
File()no valor padrão do parâmetro. - Ele utiliza um arquivo "spooled":
- Um arquivo armazenado na memória até um limite máximo de tamanho, e após passar esse limite, ele será armazenado no disco.
- Isso significa que funcionará bem para arquivos grandes como imagens, vídeos, binários grandes, etc., sem consumir toda a memória.
- Você pode receber metadados do arquivo enviado.
- Ele tem uma interface file-like
async. - Ele expõe um objeto Python
SpooledTemporaryFilereal que você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo.
UploadFile¶
UploadFile tem os seguintes atributos:
filename: Umastrcom o nome do arquivo original que foi enviado (por exemplo,myimage.jpg).content_type: Umastrcom o tipo de conteúdo (MIME type / media type) (por exemplo,image/jpeg).file: UmSpooledTemporaryFile(um objeto file-like). Este é o objeto de arquivo Python que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto semelhante a um arquivo.
UploadFile tem os seguintes métodos async. Todos eles chamam os métodos de arquivo correspondentes por baixo dos panos (usando o SpooledTemporaryFile interno).
write(data): Escrevedata(stroubytes) no arquivo.read(size): Lêsize(int) bytes/caracteres do arquivo.seek(offset): Vai para o byte na posiçãooffset(int) no arquivo.- Por exemplo,
await myfile.seek(0)irá para o início do arquivo. - Isso é especialmente útil se você executar
await myfile.read()uma vez e precisar ler o conteúdo novamente.
- Por exemplo,
close(): Fecha o arquivo.
Como todos esses métodos são métodos async, você precisa "aguardar" por eles.
Por exemplo, dentro de uma função de operação de rota async, você pode obter o conteúdo com:
contents = await myfile.read()
Se você estiver dentro de uma função de operação de rota normal def, você pode acessar o UploadFile.file diretamente, por exemplo:
contents = myfile.file.read()
Detalhes Técnicos do async
Quando você usa os métodos async, o FastAPI executa os métodos de arquivo em um threadpool e aguarda por eles.
Detalhes Técnicos do Starlette
O UploadFile do FastAPI herda diretamente do UploadFile do Starlette, mas adiciona algumas partes necessárias para torná-lo compatível com o Pydantic e as outras partes do FastAPI.
O que são "Dados de Formulário"¶
O jeito que os formulários HTML (<form></form>) enviam os dados para o servidor normalmente usa uma codificação "especial" para esses dados, a qual é diferente do JSON.
FastAPI se certificará de ler esses dados do lugar certo, ao invés de JSON.
Detalhes Técnicos
Dados de formulários normalmente são codificados usando o "media type" application/x-www-form-urlencoded quando não incluem arquivos.
Mas quando o formulário inclui arquivos, ele é codificado como multipart/form-data. Se você usar File, o FastAPI saberá que tem que pegar os arquivos da parte correta do corpo.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a documentação web da MDN para POST.
Atenção
Você pode declarar múltiplos parâmetros File e Form em uma operação de rota, mas você não pode declarar campos Body que você espera receber como JSON, pois a requisição terá o corpo codificado usando multipart/form-data ao invés de application/json.
Isso não é uma limitação do FastAPI, é parte do protocolo HTTP.
Upload de Arquivo Opcional¶
Você pode tornar um arquivo opcional usando anotações de tipo padrão e definindo um valor padrão de None:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: Annotated[bytes | None, File()] = None):
if not file:
return {"message": "No file sent"}
else:
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile | None = None):
if not file:
return {"message": "No upload file sent"}
else:
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: bytes | None = File(default=None)):
if not file:
return {"message": "No file sent"}
else:
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(file: UploadFile | None = None):
if not file:
return {"message": "No upload file sent"}
else:
return {"filename": file.filename}
UploadFile com Metadados Adicionais¶
Você também pode usar File() com UploadFile, por exemplo, para definir metadados adicionais:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: Annotated[bytes, File(description="A file read as bytes")]):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(
file: Annotated[UploadFile, File(description="A file read as UploadFile")],
):
return {"filename": file.filename}
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
app = FastAPI()
@app.post("/files/")
async defcreate_file(file: bytes = File(description="A file read as bytes")):
return {"file_size": len(file)}
@app.post("/uploadfile/")
async defcreate_upload_file(
file: UploadFile = File(description="A file read as UploadFile"),
):
return {"filename": file.filename}
Uploads de Múltiplos Arquivos¶
É possível realizar o upload de vários arquivos ao mesmo tempo.
Eles serão associados ao mesmo "campo de formulário" enviado usando "dados de formulário".
Para usar isso, declare uma lista de bytes ou UploadFile:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
fromfastapi.responsesimport HTMLResponse
app = FastAPI()
@app.post("/files/")
async defcreate_files(files: Annotated[list[bytes], File()]):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async defcreate_upload_files(files: list[UploadFile]):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async defmain():
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)
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
fromfastapi.responsesimport HTMLResponse
app = FastAPI()
@app.post("/files/")
async defcreate_files(files: list[bytes] = File()):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async defcreate_upload_files(files: list[UploadFile]):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async defmain():
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)
Você receberá, tal como declarado, uma list de bytes ou UploadFile.
Detalhes Técnicos
Você também pode usar from starlette.responses import HTMLResponse.
FastAPI providencia o mesmo starlette.responses que fastapi.responses apenas como uma conveniência para você, o desenvolvedor. Mas a maioria das respostas disponíveis vem diretamente do Starlette.
Uploads de Múltiplos Arquivos com Metadados Adicionais¶
Da mesma forma de antes, você pode usar File() para definir parâmetros adicionais, mesmo para UploadFile:
fromtypingimport Annotated
fromfastapiimport FastAPI, File, UploadFile
fromfastapi.responsesimport HTMLResponse
app = FastAPI()
@app.post("/files/")
async defcreate_files(
files: Annotated[list[bytes], File(description="Multiple files as bytes")],
):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async defcreate_upload_files(
files: Annotated[
list[UploadFile], File(description="Multiple files as UploadFile")
],
):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async defmain():
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)
🤓 Other versions and variants
Tip
Prefer to use the Annotated version if possible.
fromfastapiimport FastAPI, File, UploadFile
fromfastapi.responsesimport HTMLResponse
app = FastAPI()
@app.post("/files/")
async defcreate_files(
files: list[bytes] = File(description="Multiple files as bytes"),
):
return {"file_sizes": [len(file) for file in files]}
@app.post("/uploadfiles/")
async defcreate_upload_files(
files: list[UploadFile] = File(description="Multiple files as UploadFile"),
):
return {"filenames": [file.filename for file in files]}
@app.get("/")
async defmain():
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)
Recapitulando¶
Utilize File, bytes e UploadFile para declarar arquivos a serem enviados na requisição, enviados como dados de formulário.