11 KiB
Arquivos de Requisição
Você pode definir arquivos para serem enviados para o cliente utilizando File
.
/// info
Para receber arquivos compartilhados, primeiro instale python-multipart
.
E.g. pip install python-multipart
.
Isso se deve por que arquivos enviados são enviados como "dados de formulário".
///
Importe File
Importe File
e UploadFile
do fastapi
:
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial001_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial001_an.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível.
///
{!> ../../docs_src/request_files/tutorial001.py!}
////
Defina os parâmetros de File
Cria os parâmetros do arquivo da mesma forma que você faria para Body
ou Form
:
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial001_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial001_an.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível.
///
{!> ../../docs_src/request_files/tutorial001.py!}
////
/// info | Informação
File
é uma classe que herda diretamente de Form
.
Mas lembre-se que quando você importa Query
,Path
, File
, entre outros, do fastapi
, essas são na verdade funções que retornam classes especiais.
///
/// tip | Dica
Para declarar o corpo de arquivos, você precisa utilizar File
, do contrário os parâmetros seriam interpretados como parâmetros de consulta ou corpo (JSON) da requisição.
///
Os arquivos serão enviados como "form data".
Se você declarar o tipo do seu parâmetro na sua função de operação de rota como bytes
, o FastAPI irá ler o arquivo para você e você receberá o conteúdo como bytes
.
Lembre-se que isso significa que o conteúdo inteiro será armazenado em memória. Isso funciona bem para arquivos pequenos.
Mas existem vários casos em que você pode se beneficiar ao usar UploadFile
.
Parâmetros de arquivo com UploadFile
Defina um parâmetro de arquivo com o tipo UploadFile
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial001_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial001_an.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível.
///
{!> ../../docs_src/request_files/tutorial001.py!}
////
Utilizando UploadFile
tem várias vantagens sobre bytes
:
- Você não precisa utilizar
File()
como o valor padrão do parâmetro. - A classe utiliza um arquivo em "spool":
- Um arquivo guardado em memória até um tamanho máximo, depois desse limite ele é guardado em disco.
- Isso significa que a classe funciona bem com arquivos grandes como imagens, vídeos, binários extensos, etc. Sem consumir toda a memória.
- Você pode obter metadados do arquivo enviado.
- Ela possui uma interface semelhante a arquivos
async
. - Ela expõe um objeto python
SpooledTemporaryFile
que você pode repassar para bibliotecas que esperam um objeto com comportamento de arquivo.
UploadFile
UploadFile
tem os seguintes atributos:
filename
: Uma string (str
) com o nome original do arquivo enviado (e.g.myimage.jpg
).content-type
: Umastr
com o tipo do conteúdo (tipo MIME / media) (e.g.image/jpeg
).file
: Um objeto do tipoSpooledTemporaryFile
(um objeto file-like). O arquivo propriamente dito que você pode passar diretamente para outras funções ou bibliotecas que esperam um objeto "file-like".
UploadFile
tem os seguintes métodos async
. Todos eles chamam os métodos de arquivos por baixo dos panos (usando o objeto SpooledTemporaryFile
interno).
write(data)
: escreve dados (data
) emstr
oubytes
no arquivo.read(size)
: Lê um número de bytes/caracteres de acordo com a quantidadesize
(int
).seek(offset)
: Navega para o byte na posiçãooffset
(int
) do arquivo.- E.g.,
await myfile.seek(0)
navegaria para o ínicio do arquivo. - Isso é especialmente útil se você executar
await myfile.read()
uma vez e depois precisar ler os conteúdos do arquivo de novo.
- E.g.,
close()
: Fecha o arquivo.
Como todos esses métodos são assíncronos (async
) você precisa esperar ("await") por eles.
Por exemplo, dentro de uma função de operação de rota assíncrona você pode obter os conteúdos com:
contents = await myfile.read()
Se você estiver dentro de uma função de operação de rota definida normalmente com def
, você pode acessar UploadFile.file
diretamente, por exemplo:
contents = myfile.file.read()
/// note | Detalhes técnicos do async
Quando você utiliza métodos assíncronos, o FastAPI executa os métodos do arquivo em uma threadpool e espera por eles.
///
/// note | Detalhes técnicos do Starlette
O UploadFile
do FastAPI herda diretamente do UploadFile
do Starlette, mas adiciona algumas funcionalidades necessárias para ser compatível com o Pydantic
///
O que é "Form Data"
A forma como formulários HTML(<form></form>
) enviam dados para o servidor normalmente utilizam uma codificação "especial" para esses dados, que é diferente do JSON.
O FastAPI garante que os dados serão lidos da forma correta, em vez do JSON.
/// note | Detalhes Técnicos
Dados vindos de formulários geralmente tem a codificação com o "media type" application/x-www-form-urlencoded
quando estes não incluem arquivos.
Mas quando os dados incluem arquivos, eles são codificados como multipart/form-data
. Se você utilizar File
, FastAPI saberá que deve receber os arquivos da parte correta do corpo da requisição.
Se você quer ler mais sobre essas codificações e campos de formulário, veja a documentação online da MDN sobre POST
.
///
/// warning | Aviso
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 seriam recebidos como JSON junto desses parâmetros, por que a codificação do corpo da requisição será multipart/form-data
em vez de application/json
.
Isso não é uma limitação do FastAPI, é uma parte do protocolo HTTP.
///
Arquivo de upload opcional
Você pode definir um arquivo como opcional utilizando as anotações de tipo padrão e definindo o valor padrão como None
:
//// tab | Python 3.10+
{!> ../../docs_src/request_files/tutorial001_02_an_py310.py!}
////
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial001_02_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial001_02_an.py!}
////
//// tab | Python 3.10+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
, se possível
///
{!> ../../docs_src/request_files/tutorial001_02_py310.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
, se possível
///
{!> ../../docs_src/request_files/tutorial001_02.py!}
////
UploadFile
com Metadados Adicionais
Você também pode utilizar File()
com UploadFile
, por exemplo, para definir metadados adicionais:
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial001_03_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial001_03_an.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível
///
{!> ../../docs_src/request_files/tutorial001_03.py!}
////
Envio de Múltiplos Arquivos
É possível enviar múltiplos arquivos ao mesmo tmepo.
Ele ficam associados ao mesmo "campo do formulário" enviado com "form data".
Para usar isso, declare uma lista de bytes
ou UploadFile
:
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial002_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial002_an.py!}
////
//// tab | Python 3.9+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível
///
{!> ../../docs_src/request_files/tutorial002_py39.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível
///
{!> ../../docs_src/request_files/tutorial002.py!}
////
Você irá receber, como delcarado uma lista (list
) de bytes
ou UploadFile
s,
/// note | Detalhes Técnicos
Você também poderia utilizar from starlette.responses import HTMLResponse
.
O FastAPI fornece as mesmas starlette.responses
como fastapi.responses
apenas como um facilitador para você, desenvolvedor. Mas a maior parte das respostas vem diretamente do Starlette.
///
Enviando Múltiplos Arquivos com Metadados Adicionais
E da mesma forma que antes, você pode utilizar File()
para definir parâmetros adicionais, até mesmo para UploadFile
:
//// tab | Python 3.9+
{!> ../../docs_src/request_files/tutorial003_an_py39.py!}
////
//// tab | Python 3.8+
{!> ../../docs_src/request_files/tutorial003_an.py!}
////
//// tab | Python 3.9+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível.
///
{!> ../../docs_src/request_files/tutorial003_py39.py!}
////
//// tab | Python 3.8+ non-Annotated
/// tip | Dica
Utilize a versão com Annotated
se possível.
///
{!> ../../docs_src/request_files/tutorial003.py!}
////
Recapitulando
Use File
, bytes
e UploadFile
para declarar arquivos que serão enviados na requisição, enviados como dados do formulário.