python - 响应上传确认,然后在 Sanic 中处理文件

标签 python api asynchronous 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 - 流式响应

此选项是流式响应,您可以立即发回第一部分,然后根据需要继续处理响应。现在,这显然在某种程度上取决于我们正在讨论的处理量。如果它有点长(选择任意时间,60 秒),那么这个解决方案可能不起作用。

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 - 后台任务

我相信这正是您所寻找的。立即响应(关闭连接)。我们进行处理并使用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我把它放在一起,处理程序将任务推送到队列,并且有一个单独的“工作人员”正在排空队列并执行任务。

关于python - 响应上传确认,然后在 Sanic 中处理文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/63321111/

相关文章:

jquery - Flask AJAX 自动完成

python - python BaseHttpServer 支持 Html5 吗?

javascript - AngularJS 和异步调用

javascript - 如何在 web pack 2 中异步加载 1 个以上模块?

python - 如何在启动 Tkinter 应用程序时隐藏控制台窗口,但在按下 GUI 按钮运行 python 脚本时重新打开它?

python - 阅读文本文件

api - 保护公共(public) API

amazon-web-services - 将 AWS API Gateway API 端点的 IP 列入公司防火墙中的白名单

api - Telegram channel 的帖子观看次数

c# - ContinueWith 作为 await 运算符的替代