繁体   English   中英

如何使用表单数据和文件显示 aiohttp POST 的进度

[英]How to show progress on aiohttp POST with both form data and file

好的,这是我的工作代码:

data = aiohttp.FormData()
data.add_field('title', title)
data.add_field('author', user)
data.add_field('upload_file', open(path, 'rb'))

up_session = aiohttp.ClientSession()
async with up_session.post(url="http://example.com/upload.php", data=data) as response:
    resp = await response.text()

resp = json.loads(resp)

我想知道的是如何为其添加某种进度监控。 我在文档中找不到任何类型的回调,也找不到与 MultipartWriter 一起使用的生成器(FormData 只是 MultipartWriter 的助手)。 我在这里失去理智。 提前致谢。

编辑:我曾经使用 request 和 requeststoolbelt (MultipartEncoder, MultipartEncoderMonitor) 来获取它,但它们不是异步的,而且 aiohttp 是一个如此完整的库,我不敢相信你不能这样做。

    encoder = MultipartEncoder(
    fields={
    'upload_file': (ntpath.basename(path), open(path, 'rb'), 
    'application/octet-stream'),
    'title': str(''),
    'author': str(user),
    })
    upload_data = MultipartEncoderMonitor(encoder, upload_progress)

    headers={'Content-Type': upload_data.content_type}
    headers.update(http_headers)
    
    r_2 = session.post(url=url_domain + "/repository/repository_ajax.php?action=upload", data=upload_data)

def upload_progress(monitor):
    print (str(monitor.len) + " - " + "{:.2f}%".format(monitor.bytes_read/monitor.len))

天哪,我忘记了这个老问题。 我确实找到了一个解决方案,有点笨拙,但它可以工作,并且对于其他不提供良好进度跟踪但接受二元流的库来说有点通用。 它是 BufferedReader 的包装器。 从技术上讲,在读取字节而不是发送字节时对其进行计数,但对于进度条来说,它有点相同。

from pathlib import Path from io import BufferedReader from aiohttp import ClientSession

class ProgressFileReader(BufferedReader):
    def __init__(self, filename, read_callback=None):
        f = open(filename, "rb")
        self.__read_callback = read_callback
        super().__init__(raw=f)
        self.length = Path(filename).stat().st_size

    def read(self, size=None):
        calc_sz = size
        if not calc_sz:
            calc_sz = self.length - self.tell()
        if self.__read_callback:
            self.__read_callback(self.tell(), self.length)
        return super(ProgressFileReader, self).read(size)


def progress_callback(current, total):
    print(100 * current // total)


async def main():
    with ProgressFileReader(filename="./file.jpg", read_callback=progress_callback) as file:
        upload_payload = {
            "foo": "bar",
            "file": file,
        }
        async with ClientSession() as session:
            async with session.post("http://example.org", data=upload_payload) as response:
                resp = await response.text()

包装器本身是同步的,但它不是什么大问题,如果你包裹 aiofiles 而不是内置的“open”,它可以被异步化。 将包装器 class 想法归功于我现在找不到的其他一些 stackoverflow 问题。 仅此而已... 英语不好,抱歉。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM