Archivos de Request¶
Puedes definir archivos que serán subidos por el cliente utilizandoFile.
Información
Para recibir archivos subidos, primero instalapython-multipart.
Asegúrate de crear unentorno virtual, activarlo y luego instalarlo, por ejemplo:
$pipinstallpython-multipartEsto es porque los archivos subidos se envían como "form data".
ImportarFile¶
ImportaFile yUploadFile desdefastapi:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}🤓 Other versions and variants
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File()):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}Definir ParámetrosFile¶
Crea parámetros de archivo de la misma manera que lo harías paraBody oForm:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}🤓 Other versions and variants
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File()):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}Información
File es una clase que hereda directamente deForm.
Pero recuerda que cuando importasQuery,Path,File y otros desdefastapi, esos son en realidad funciones que devuelven clases especiales.
Consejo
Para declarar cuerpos de File, necesitas usarFile, porque de otra manera los parámetros serían interpretados como parámetros query o parámetros de cuerpo (JSON).
Los archivos se subirán como "form data".
Si declaras el tipo de tu parámetro depath operation function comobytes,FastAPI leerá el archivo por ti y recibirás el contenido comobytes.
Ten en cuenta que esto significa que todo el contenido se almacenará en memoria. Esto funcionará bien para archivos pequeños.
Pero hay varios casos en los que podrías beneficiarte de usarUploadFile.
Parámetros de Archivo conUploadFile¶
Define un parámetro de archivo con un tipo deUploadFile:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}🤓 Other versions and variants
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File()]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File()):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile):return{"filename":file.filename}UsarUploadFile tiene varias ventajas sobrebytes:
- No tienes que usar
File()en el valor por defecto del parámetro. - Usa un archivo "spooled":
- Un archivo almacenado en memoria hasta un límite de tamaño máximo, y después de superar este límite, se almacenará en el disco.
- Esto significa que funcionará bien para archivos grandes como imágenes, videos, binarios grandes, etc. sin consumir toda la memoria.
- Puedes obtener metadatos del archivo subido.
- Tiene una interfaz
asyncparecida a un archivo. - Expone un objeto Python real
SpooledTemporaryFileque puedes pasar directamente a otros paquetes que esperan un objeto parecido a un archivo.
UploadFile¶
UploadFile tiene los siguientes atributos:
filename: Unstrcon el nombre original del archivo que fue subido (por ejemplo,myimage.jpg).content_type: Unstrcon el tipo de contenido (MIME type / media type) (por ejemplo,image/jpeg).file: UnSpooledTemporaryFile(un objetoparecido a un archivo). Este es el objeto de archivo Python real que puedes pasar directamente a otras funciones o paquetes que esperan un objeto "parecido a un archivo".
UploadFile tiene los siguientes métodosasync. Todos ellos llaman a los métodos correspondientes del archivo por debajo (usando elSpooledTemporaryFile interno).
write(data): Escribedata(strobytes) en el archivo.read(size): Leesize(int) bytes/caracteres del archivo.seek(offset): Va a la posición de bytesoffset(int) en el archivo.- Por ejemplo,
await myfile.seek(0)iría al inicio del archivo. - Esto es especialmente útil si ejecutas
await myfile.read()una vez y luego necesitas leer el contenido nuevamente.
- Por ejemplo,
close(): Cierra el archivo.
Como todos estos métodos son métodosasync, necesitas "await" para ellos.
Por ejemplo, dentro de unapath operation functionasync puedes obtener los contenidos con:
contents=awaitmyfile.read()Si estás dentro de unapath operation function normaldef, puedes acceder alUploadFile.file directamente, por ejemplo:
contents=myfile.file.read()Detalles Técnicos deasync
Cuando usas los métodosasync,FastAPI ejecuta los métodos del archivo en un threadpool y los espera.
Detalles Técnicos de Starlette
ElUploadFile deFastAPI hereda directamente delUploadFile deStarlette, pero añade algunas partes necesarias para hacerlo compatible conPydantic y las otras partes de FastAPI.
Qué es "Form Data"¶
La manera en que los forms de HTML (<form></form>) envían los datos al servidor normalmente utiliza una codificación "especial" para esos datos, es diferente de JSON.
FastAPI se asegurará de leer esos datos del lugar correcto en lugar de JSON.
Detalles Técnicos
Los datos de los forms normalmente se codifican usando el "media type"application/x-www-form-urlencoded cuando no incluyen archivos.
Pero cuando el formulario incluye archivos, se codifica comomultipart/form-data. Si usasFile,FastAPI sabrá que tiene que obtener los archivos de la parte correcta del cuerpo.
Si deseas leer más sobre estas codificaciones y campos de formularios, dirígete a laMDN web docs paraPOST.
Advertencia
Puedes declarar múltiples parámetrosFile yForm en unapath operation, pero no puedes declarar camposBody que esperas recibir como JSON, ya que el request tendrá el cuerpo codificado usandomultipart/form-data en lugar deapplication/json.
Esto no es una limitación deFastAPI, es parte del protocolo HTTP.
Subida de Archivos Opcional¶
Puedes hacer un archivo opcional utilizando anotaciones de tipos estándar y estableciendo un valor por defecto deNone:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes|None,File()]=None):ifnotfile:return{"message":"No file sent"}else:return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile|None=None):ifnotfile:return{"message":"No upload file sent"}else:return{"filename":file.filename}🤓 Other versions and variants
fromtypingimportAnnotated,UnionfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[Union[bytes,None],File()]=None):ifnotfile:return{"message":"No file sent"}else:return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Union[UploadFile,None]=None):ifnotfile:return{"message":"No upload file sent"}else:return{"filename":file.filename}fromtypingimportUnionfromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[Union[bytes,None],File()]=None):ifnotfile:return{"message":"No file sent"}else:return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Union[UploadFile,None]=None):ifnotfile:return{"message":"No upload file sent"}else:return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes|None=File(default=None)):ifnotfile:return{"message":"No file sent"}else:return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile|None=None):ifnotfile:return{"message":"No upload file sent"}else:return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromtypingimportUnionfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Union[bytes,None]=File(default=None)):ifnotfile:return{"message":"No file sent"}else:return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Union[UploadFile,None]=None):ifnotfile:return{"message":"No upload file sent"}else:return{"filename":file.filename}UploadFile con Metadatos Adicionales¶
También puedes usarFile() conUploadFile, por ejemplo, para establecer metadatos adicionales:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}🤓 Other versions and variants
fromfastapiimportFastAPI,File,UploadFilefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:Annotated[bytes,File(description="A file read as bytes")]):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:Annotated[UploadFile,File(description="A file read as UploadFile")],):return{"filename":file.filename}Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFileapp=FastAPI()@app.post("/files/")asyncdefcreate_file(file:bytes=File(description="A file read as bytes")):return{"file_size":len(file)}@app.post("/uploadfile/")asyncdefcreate_upload_file(file:UploadFile=File(description="A file read as UploadFile"),):return{"filename":file.filename}Subidas de Múltiples Archivos¶
Es posible subir varios archivos al mismo tiempo.
Estarían asociados al mismo "campo de formulario" enviado usando "form data".
Para usar eso, declara una lista debytes oUploadFile:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:Annotated[list[bytes],File()]):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:list[UploadFile]):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)🤓 Other versions and variants
fromtypingimportListfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponsefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:Annotated[List[bytes],File()]):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:List[UploadFile]):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:list[bytes]=File()):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:list[UploadFile]):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Tip
Prefer to use theAnnotated version if possible.
fromtypingimportListfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:List[bytes]=File()):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:List[UploadFile]):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Recibirás, como se declaró, unalist debytes oUploadFiles.
Detalles Técnicos
También podrías usarfrom starlette.responses import HTMLResponse.
FastAPI proporciona las mismasstarlette.responses comofastapi.responses solo como una conveniencia para ti, el desarrollador. Pero la mayoría de los responses disponibles vienen directamente de Starlette.
Subidas de Múltiples Archivos con Metadatos Adicionales¶
Y de la misma manera que antes, puedes usarFile() para establecer parámetros adicionales, incluso paraUploadFile:
fromtypingimportAnnotatedfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:Annotated[list[bytes],File(description="Multiple files as bytes")],):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:Annotated[list[UploadFile],File(description="Multiple files as UploadFile")],):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)🤓 Other versions and variants
fromtypingimportListfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponsefromtyping_extensionsimportAnnotatedapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:Annotated[List[bytes],File(description="Multiple files as bytes")],):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:Annotated[List[UploadFile],File(description="Multiple files as UploadFile")],):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Tip
Prefer to use theAnnotated version if possible.
fromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:list[bytes]=File(description="Multiple files as bytes"),):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:list[UploadFile]=File(description="Multiple files as UploadFile"),):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Tip
Prefer to use theAnnotated version if possible.
fromtypingimportListfromfastapiimportFastAPI,File,UploadFilefromfastapi.responsesimportHTMLResponseapp=FastAPI()@app.post("/files/")asyncdefcreate_files(files:List[bytes]=File(description="Multiple files as bytes"),):return{"file_sizes":[len(file)forfileinfiles]}@app.post("/uploadfiles/")asyncdefcreate_upload_files(files:List[UploadFile]=File(description="Multiple files as UploadFile"),):return{"filenames":[file.filenameforfileinfiles]}@app.get("/")asyncdefmain():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> """returnHTMLResponse(content=content)Recapitulación¶
UsaFile,bytes yUploadFile para declarar archivos que se subirán en el request, enviados como form data.







