You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何优化Python实现30MB图片的毫秒级下载?

针对大尺寸图片高效下载的优化方案

现有requests代码的改进点

  • 流式下载+分块写入:避免一次性把30MB内容加载到内存,边下载边写入磁盘,减少内存占用同时提升写入效率。示例代码:
    import requests
    import os
    
    def download_image(url, save_folder):
        os.makedirs(save_folder, exist_ok=True)
        filename = url.split("/")[-1]
        save_path = os.path.join(save_folder, filename)
        
        # 使用Session复用连接
        with requests.Session() as session:
            # 流式获取响应
            with session.get(url, stream=True, timeout=10) as r:
                r.raise_for_status()
                # 设置合适的块大小
                with open(save_path, 'wb') as f:
                    for chunk in r.iter_content(chunk_size=16384):
                        if chunk:
                            f.write(chunk)
    
  • 复用TCP连接:用requests.Session()替代单次请求,复用底层TCP连接,减少TCP握手的时间开销。
  • 添加重试机制:针对网络波动设置自动重试,避免单次请求失败中断流程:
    from requests.adapters import HTTPAdapter
    from urllib3.util.retry import Retry
    
    def create_session():
        session = requests.Session()
        retry = Retry(total=3, backoff_factor=0.5, status_forcelist=[500, 502, 503, 504])
        adapter = HTTPAdapter(max_retries=retry)
        session.mount('http://', adapter)
        session.mount('https://', adapter)
        return session
    
  • 并行下载:用多线程处理多个图片URL,避免单线程等待串行执行:
    from concurrent.futures import ThreadPoolExecutor
    
    if __name__ == "__main__":
        image_urls = ["https://example.com/image1.jpg", "https://example.com/image2.jpg"]
        save_folder = "downloaded_images"
        
        with ThreadPoolExecutor(max_workers=4) as executor:
            executor.map(lambda url: download_image(url, save_folder), image_urls)
    

高效的替代库与方法

  • aiohttp(异步下载):适合高并发场景,基于异步IO模型,比多线程更少资源开销,示例:
    import aiohttp
    import asyncio
    import os
    
    async def download_image_async(url, save_folder):
        os.makedirs(save_folder, exist_ok=True)
        filename = url.split("/")[-1]
        save_path = os.path.join(save_folder, filename)
        
        async with aiohttp.ClientSession() as session:
            async with session.get(url, timeout=10) as r:
                r.raise_for_status()
                with open(save_path, 'wb') as f:
                    while chunk := await r.content.read(16384):
                        f.write(chunk)
    
    async def main():
        image_urls = ["https://example.com/image1.jpg", "https://example.com/image2.jpg"]
        save_folder = "downloaded_images"
        tasks = [download_image_async(url, save_folder) for url in image_urls]
        await asyncio.gather(*tasks)
    
    if __name__ == "__main__":
        asyncio.run(main())
    
  • curl-cffi:基于libcurl的绑定,性能优于requests,支持HTTP/2,适合大文件下载。
  • wget:专门的下载工具库,内置断点续传、进度条等功能,代码极简:
    import wget
    import os
    
    def download_image_wget(url, save_folder):
        os.makedirs(save_folder, exist_ok=True)
        wget.download(url, out=save_folder)
    

通用优化技巧与最佳实践

  • 断点续传:检查本地文件大小,发送Range请求头获取剩余部分,避免重复下载已完成的内容。
  • 启用压缩传输:在请求头中添加Accept-Encoding: gzip, deflate,让服务器返回压缩后的内容,减少传输数据量。
  • 本地缓存:对已下载的图片记录URL和本地路径,后续请求优先读取本地文件,避免重复请求服务器。
  • 调整块大小:根据磁盘IO性能调整chunk_size,一般16KB-64KB是比较均衡的选择,过小会增加IO次数,过大则占用更多内存。
  • 跳过不必要的处理:下载阶段仅做字节流写入,不要解析图片内容(如PIL打开),避免额外性能开销。
  • 选择HTTP/2协议:部分库支持HTTP/2,可复用连接并并行发送请求,提升多文件下载效率。

内容的提问来源于stack exchange,提问作者kairoon bodanapu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 04:52:44