响应上传确认,然后在 Sanic 中处理文件
Respond to an Upload confimation and then process file in Sanic
我正在尝试处理用户上传的文件。但是,我希望用户在上传完成后得到响应并终止连接但继续处理文件。我的代码看起来像这样:
@app.route("/upload", methods=['POST'])
async def upload(request):
try:
file = request.files.get("file")
except Exception as e:
return json({"Received": False})
await process(file)
return response.text("File has been uploaded successfully")
async def process(file):
""" Processing File and generate data"""
...
result = await foo(data)
在当前框架中,用户必须等到进程完成。我希望用户收到这样的回复:
"File has been uploaded successfully"
并终止连接但仍继续处理(文件)。
我认为您在这里有两种可能的解决方案。第一个会稍微偏离您的要求,因为它不会终止连接。但是,我认为这是一个可行的解决方案,所以我也提供了它。如果不是为了您的利益,也许是为了其他有类似需求的人。
选项 #1 - 流式响应
此选项是一个流式响应,您可以立即发回第一部分,然后根据需要继续处理响应。现在,这显然在某种程度上取决于我们正在谈论的 处理方式。如果它有点长(选择任意时间,60s),那么这个解决方案可能不起作用。
import asyncio
from functools import partial
from sanic import Sanic
from sanic.response import json, stream
app = Sanic(__name__)
async def process(file, response):
print(file, flush=True)
await response.protocol.push_data(b"0x0")
await response.write("File has been uploaded successfully\n")
await asyncio.sleep(2)
await response.write("33% processed\n")
await asyncio.sleep(2)
await response.write("66% processed\n")
await asyncio.sleep(2)
await response.write("100% processed\n")
@app.post("/")
async def upload(request):
try:
file = request.files.get("file")
except Exception:
return json({"Received": False})
return stream(partial(process, file), chunked=False)
选项 #2 - 后台任务
我相信这就是您要找的。立即响应(关闭连接)。我们获取 processing
并使用 add_task
.
将其推到后台
import asyncio
from functools import partial
from sanic import Sanic
from sanic.response import json, text
app = Sanic(__name__)
async def process(file,):
await asyncio.sleep(3)
print(f"{file=}", flush=True)
@app.post("/")
async def upload(request):
try:
file = request.files.get("file")
except Exception:
return json({"Received": False})
request.app.add_task(process(file))
return text("File has been uploaded successfully")
作为另一种选择,我将 here is an example 放在一起,其中处理程序将任务推送到队列,并且有一个单独的“工作程序”正在排空队列并执行任务。
我正在尝试处理用户上传的文件。但是,我希望用户在上传完成后得到响应并终止连接但继续处理文件。我的代码看起来像这样:
@app.route("/upload", methods=['POST'])
async def upload(request):
try:
file = request.files.get("file")
except Exception as e:
return json({"Received": False})
await process(file)
return response.text("File has been uploaded successfully")
async def process(file):
""" Processing File and generate data"""
...
result = await foo(data)
在当前框架中,用户必须等到进程完成。我希望用户收到这样的回复:
"File has been uploaded successfully"
并终止连接但仍继续处理(文件)。
我认为您在这里有两种可能的解决方案。第一个会稍微偏离您的要求,因为它不会终止连接。但是,我认为这是一个可行的解决方案,所以我也提供了它。如果不是为了您的利益,也许是为了其他有类似需求的人。
选项 #1 - 流式响应
此选项是一个流式响应,您可以立即发回第一部分,然后根据需要继续处理响应。现在,这显然在某种程度上取决于我们正在谈论的 处理方式。如果它有点长(选择任意时间,60s),那么这个解决方案可能不起作用。
import asyncio
from functools import partial
from sanic import Sanic
from sanic.response import json, stream
app = Sanic(__name__)
async def process(file, response):
print(file, flush=True)
await response.protocol.push_data(b"0x0")
await response.write("File has been uploaded successfully\n")
await asyncio.sleep(2)
await response.write("33% processed\n")
await asyncio.sleep(2)
await response.write("66% processed\n")
await asyncio.sleep(2)
await response.write("100% processed\n")
@app.post("/")
async def upload(request):
try:
file = request.files.get("file")
except Exception:
return json({"Received": False})
return stream(partial(process, file), chunked=False)
选项 #2 - 后台任务
我相信这就是您要找的。立即响应(关闭连接)。我们获取 processing
并使用 add_task
.
import asyncio
from functools import partial
from sanic import Sanic
from sanic.response import json, text
app = Sanic(__name__)
async def process(file,):
await asyncio.sleep(3)
print(f"{file=}", flush=True)
@app.post("/")
async def upload(request):
try:
file = request.files.get("file")
except Exception:
return json({"Received": False})
request.app.add_task(process(file))
return text("File has been uploaded successfully")
作为另一种选择,我将 here is an example 放在一起,其中处理程序将任务推送到队列,并且有一个单独的“工作程序”正在排空队列并执行任务。