[英]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.