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
SpooledTemporaryFileque 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: Umastrcom 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) emstroubytesno 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 Bodyque 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 UploadFiles,
/// 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.