使用 aiohttp 和 python 下载具有恢复功能的文件

Download file with resume capability using aiohttp and python

我想使用 aiohttp 流式传输和下载文件。 Chrome可以支持下载续传能力link 但是下载管理器无法下载具有续传功能的文件。

在下面的代码中,我使用了 aiohttp 框架来流式传输和下载文件, 我还设置了 header 参数 ('Accept-Ranges') 以支持恢复功能。

from telethon import TelegramClient, events
client = TelegramClient(name, api_id,api_hash)

@routes.get('/{userid}/{msgid}')
async def handle(request):
    ...
    response = web.StreamResponse(
        status=200,
        reason='OK',
        headers={
            'Content-Type': content_type,
            'Content-Length':str(file_size),
            'Accept-Ranges': 'bytes',
            'Connection': 'keep-alive',
        }
    )
    await response.prepare(request)
    async for chunk in client.iter_download(msg.media, chunk_size=512):
        await response.write(chunk)
    return response

app = web.Application()
app.add_routes(routes)
web.run_app(app,host='0.0.0.0')

在浏览器中点击下载 link 时,文件流式传输良好。 Chrome 很好地支持恢复功能, 我希望下载管理器能够很好地支持恢复功能,但是在暂停并再次开始下载后,下载管理器无法继续下载并需要用户重新开始下载。 消息 IDM 给出:"When trying to resume the download, internet download manager got response from the server that it does not support resuming the download ..."

立足于此streamer implementation, it seems like you are missing Content-Range and status=206 to indicate Partial Content

可能像下面这样的东西可能会起作用。请注意,它没有进行足够的验证(即 headers 中的 Range 可能无效)。

import re

...

async def handle(request):
    offset = request.headers.get('Range', 0)
    if not isinstance(offset, int):
        offset = int(re.match(r'bytes=(\d+)', offset).group(1))

    size = message.file.size
    response = web.StreamResponse(
        headers={
            'Content-Type': 'application/octet-stream',
            'Accept-Ranges': 'bytes',
            'Content-Range': f'bytes {offset}-{size}/{size}'
        },
        status=206 if offset else 200,
    )
    await response.prepare(request)

    async for part in client.iter_download(message.media, offset=offset):
        await response.write(part)

    return response