如何将文件对象传递给 FastAPI 端点中的 HTTPX 请求
How to pass File object to HTTPX request in FastAPI endpoint
想法是从一个端点获取文件对象并将其发送到其他端点以使用它而不保存它。
让我们有这个示例代码:
import httpx
from fastapi import Request, UploadFile, File
app = FastAPI()
client = httpx.AsyncClient()
@app.post("/endpoint/")
async def foo(request: Request, file: UploadFile = File(...))
urls = ["/some/other/endpoint", "/another/endpoint/"]
for url in urls:
response = await client.post(url) # here I need to send the file to the other endpoint
return {"bar": "baz"}
@app.post("/some/other/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)): # and here to use it
# Do something with the file object
return {"file": file.filename}
@app.post("/another/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)): # and here to use it too
# Do something with the file object
return {"file": file.content_type}
如前所述here我试过这样做:
data = {'file': file}
response = await client.post(url, data=data)
但是出错了
'{"detail":[{"loc":["body","file"],"msg":"Expected UploadFile, received: <class \'str\'>","type":"value_error"}]}'
卷曲请求示例:
curl -X 'POST' -F 'file=@somefile' someserver/endpoint/
httpx
类似于requests
使用files=....
发送文件。
即
post(..., files={'file': file.file}, ...)
或使用文件名
post(..., files={'file': (file.filename, file.file)}, ...)
顺便说一句:
如果多次发送同一个文件,则可能需要在发送后将指针移至文件开头
file.file.seek(0)
或
await file.seek(0)
完整的工作代码
from fastapi import FastAPI, Request, UploadFile, File
import httpx
app = FastAPI()
client = httpx.AsyncClient()
@app.post("/endpoint/")
async def foo(request: Request, file: UploadFile = File(...)):
print('/endpoint/')
urls = ["/some/other/endpoint/", "/another/endpoint/"]
results = []
for url in urls:
response = await client.post('http://localhost:8000' + url, files={'file': (file.filename, file.file)})
#file.file.seek(0) # move back at the beginning of file after sending to other URL
await file.seek(0) # move back at the beginning of file after sending to other URL
results.append(response)
results = [item.text for item in results]
print('results:', results)
return {"bar": "baz"}
@app.post("/some/other/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)):
print('/some/other/endpoint/')
print('filename:', file.filename)
print('content_type:', file.content_type)
# Do something with the file object
return {"file": file.filename}
@app.post("/another/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)):
print('/another/endpoint/')
print('filename:', file.filename)
print('content_type:', file.content_type)
# Do something with the file object
return {"file": file.content_type}
想法是从一个端点获取文件对象并将其发送到其他端点以使用它而不保存它。 让我们有这个示例代码:
import httpx
from fastapi import Request, UploadFile, File
app = FastAPI()
client = httpx.AsyncClient()
@app.post("/endpoint/")
async def foo(request: Request, file: UploadFile = File(...))
urls = ["/some/other/endpoint", "/another/endpoint/"]
for url in urls:
response = await client.post(url) # here I need to send the file to the other endpoint
return {"bar": "baz"}
@app.post("/some/other/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)): # and here to use it
# Do something with the file object
return {"file": file.filename}
@app.post("/another/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)): # and here to use it too
# Do something with the file object
return {"file": file.content_type}
如前所述here我试过这样做:
data = {'file': file}
response = await client.post(url, data=data)
但是出错了
'{"detail":[{"loc":["body","file"],"msg":"Expected UploadFile, received: <class \'str\'>","type":"value_error"}]}'
卷曲请求示例:
curl -X 'POST' -F 'file=@somefile' someserver/endpoint/
httpx
类似于requests
使用files=....
发送文件。
即
post(..., files={'file': file.file}, ...)
或使用文件名
post(..., files={'file': (file.filename, file.file)}, ...)
顺便说一句:
如果多次发送同一个文件,则可能需要在发送后将指针移至文件开头
file.file.seek(0)
或
await file.seek(0)
完整的工作代码
from fastapi import FastAPI, Request, UploadFile, File
import httpx
app = FastAPI()
client = httpx.AsyncClient()
@app.post("/endpoint/")
async def foo(request: Request, file: UploadFile = File(...)):
print('/endpoint/')
urls = ["/some/other/endpoint/", "/another/endpoint/"]
results = []
for url in urls:
response = await client.post('http://localhost:8000' + url, files={'file': (file.filename, file.file)})
#file.file.seek(0) # move back at the beginning of file after sending to other URL
await file.seek(0) # move back at the beginning of file after sending to other URL
results.append(response)
results = [item.text for item in results]
print('results:', results)
return {"bar": "baz"}
@app.post("/some/other/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)):
print('/some/other/endpoint/')
print('filename:', file.filename)
print('content_type:', file.content_type)
# Do something with the file object
return {"file": file.filename}
@app.post("/another/endpoint/")
async def baz(request: Request, file: UploadFile = File(...)):
print('/another/endpoint/')
print('filename:', file.filename)
print('content_type:', file.content_type)
# Do something with the file object
return {"file": file.content_type}