7.8 KiB
Arquivos de Requisição
Você pode definir arquivos para serem enviados pelo cliente usando File.
/// info | Informação
Para receber arquivos enviados, primeiro instale o python-multipart.
Garanta que você criou um ambiente virtual{.internal-link target=_blank}, o ativou e então o instalou, por exemplo:
$ pip install python-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:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[3] *}
Definir Parâmetros File
Crie parâmetros de arquivo da mesma forma que você faria para Body ou Form:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[9] *}
/// info | Informação
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.
///
/// tip | 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 função da sua 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:
{* ../../docs_src/request_files/tutorial001_an_py39.py hl[14] *}
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 file-like interface
assíncrona. - Ele expõe um objeto python
SpooledTemporaryFileque você pode passar diretamente para outras bibliotecas que esperam um objeto semelhante a um arquivo("file-like").
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 (tipo MIME / tipo de mídia) (por exemplo,image/jpeg).file: UmSpooledTemporaryFile(um file-like objeto). 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("file-like").
UploadFile tem os seguintes métodos assíncronos. 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 assíncronos, você precisa "aguardar" por eles.
Por exemplo, dentro de uma função de operação de rota assíncrona, 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()
/// note | 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.
///
/// note | "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 é "Form Data"
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.
/// note | "Detalhes Técnicos"
Dados de formulários normalmente são codificados usando o "media type" (tipo de mídia) 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 da requisição.
Se você quiser ler mais sobre essas codificações e campos de formulário, vá para a MDN web docs para 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 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:
{* ../../docs_src/request_files/tutorial001_02_an_py310.py hl[9,17] *}
UploadFile com Metadados Adicionais
Você também pode usar File() com UploadFile, por exemplo, para definir metadados adicionais:
{* ../../docs_src/request_files/tutorial001_03_an_py39.py hl[9,15] *}
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:
{* ../../docs_src/request_files/tutorial002_an_py39.py hl[10,15] *}
Você receberá, tal como declarado, uma list de bytes ou UploadFile.
/// note | "Detalhes Técnicos"
Você pode 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:
{* ../../docs_src/request_files/tutorial003_an_py39.py hl[11,18:20] *}
Recapitulando
Utilize File, bytes e UploadFile para declarar arquivos a serem enviados na requisição, enviados como dados de formulário.