Estoy usando FastAPI para cargar archivos de acuerdo con la documentación oficial, como:
@app.post("/create_file/") async def create_file(file: UploadFile=File(...)): file2store = await file.read() # some code to store the BytesIO(file2store) to the other databaseCuando envío una solicitud usando Python Requests lib:
f = open(".../file.txt", 'rb') files = {"file": (f.name, f, "multipart/form-data")} requests.post(url="SERVER_URL/create_file", files=files) el file2store siempre está vacío. A veces (rara vez visto), puede obtener los bytes del archivo, pero casi todo el tiempo está vacío, por lo que no puedo restaurar el archivo en la otra base de datos.
También probé los bytes en lugar de UploadFile , obtengo los mismos resultados. ¿Hay algún error en mi código, o es incorrecta la forma en que uso FastAPI para cargar el archivo? Busqué en Google algunas respuestas durante mucho tiempo, pero fallé. Así que planteo el problema aquí, esperando que alguien que sepa la respuesta pueda ayudarme.
Tenga en cuenta que la respuesta a continuación utiliza la escritura síncrona para escribir los archivos en el disco. Si necesita escritura asincrónica , eche un vistazo a esta respuesta . Además, si necesita enviar datos adicionales (como datos JSON ) junto con la carga de los archivos, consulte esta respuesta . Le sugiero que también eche un vistazo a esta respuesta , que explica la diferencia entre definir un punto final con def y async def , y demuestra cómo leer el contents de un archivo cargado cuando se usa def (si ese es un requisito para su aplicación) .
app.py
import uvicorn from fastapi import File, UploadFile, FastAPI app = FastAPI() @app.post("/upload") async def upload(file: UploadFile = File(...)): try: contents = await file.read() with open(file.filename, 'wb') as f: f.write(contents) except Exception: return {"message": "There was an error uploading the file"} finally: await file.close() return {"message": f"Successfuly uploaded {file.filename}"} if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000)prueba.py
import requests url = 'http://127.0.0.1:8000/upload' file = {'file': open('images/1.png', 'rb')} resp = requests.post(url=url, files=file) print(resp.json())app.py
import uvicorn from fastapi import File, UploadFile, FastAPI from typing import List app = FastAPI() @app.post("/upload") async def upload(files: List[UploadFile] = File(...)): for file in files: try: contents = await file.read() with open(file.filename, 'wb') as f: f.write(contents) except Exception: return {"message": "There was an error uploading the file(s)"} finally: await file.close() return {"message": f"Successfuly uploaded {[file.filename for file in files]}"} if __name__ == '__main__': uvicorn.run(app, host='0.0.0.0', port=8000)prueba.py
import requests url = 'http://127.0.0.1:8000/upload' files = [('files', open('images/1.png', 'rb')), ('files', open('images/2.png', 'rb'))] resp = requests.post(url=url, files=files) print(resp.json())@app.post("/create_file/") async def image(image: UploadFile = File(...)): print(image.file) # print('../'+os.path.isdir(os.getcwd()+"images"),"*************") try: os.mkdir("images") print(os.getcwd()) except Exception as e: print(e) file_name = os.getcwd()+"/images/"+image.filename.replace(" ", "-") with open(file_name,'wb+') as f: f.write(image.file.read()) f.close() file = jsonable_encoder({"imagePath":file_name}) new_image = await add_image(file) return {"filename": new_image}Trabajé en él hace casi 7 u 8 meses, no encontré el problema que dices. Descubrí que UploadFile es del tipo SpooledTemproaryFile y no intenté leer el archivo de forma asíncrona. Aquí está el fragmento que se está utilizando. He subido todo tipo de archivos hasta 100mb, está funcionando. Tuve que guardar el archivo en el servidor en una ruta específica
with open(path, 'wb') as f: [f.write(chunk) for chunk in iter(lambda: file.file.read(10000), b'')]En su caso, sugeriría leer el archivo y hacer la solicitud de publicación directamente usando sesiones aiohttp o AsyncClient de httpx