如何用Python提高文件上传速度

需要提供一个接口,接口接收客户端上传的文件,然后进行特定处理,把结果返回客户端。

现在的问题是,如何提高上传的速度? 提高服务器带宽?使用压缩?

服务端可以做哪些工作提高上传的速度?


如何用Python提高文件上传速度
10 回复

服务端的下载带宽就是客户端最大可用的上传带宽。不过在国内来说,客户端上传都好不到哪里去,除非是公司上下对待的商业宽带。


对于用Python提高文件上传速度,核心是减少网络往返和利用并行传输。这里给你几个实用的方案:

1. 使用流式上传和分块传输

import requests
from requests_toolbelt.multipart.encoder import MultipartEncoder

# 流式上传大文件
def upload_large_file(file_path, url, chunk_size=8192):
    with open(file_path, 'rb') as f:
        encoder = MultipartEncoder(
            fields={'file': ('filename', f, 'application/octet-stream')}
        )
        
        headers = {'Content-Type': encoder.content_type}
        
        # 分块上传
        response = requests.post(
            url, 
            data=encoder, 
            headers=headers,
            stream=True
        )
    return response

2. 多线程并行上传

from concurrent.futures import ThreadPoolExecutor
import os

def upload_chunk(chunk_data, chunk_num, url):
    files = {'chunk': (f'chunk_{chunk_num}', chunk_data)}
    return requests.post(url, files=files)

def parallel_upload(file_path, url, max_workers=4, chunk_size=1024*1024):
    chunks = []
    with open(file_path, 'rb') as f:
        while True:
            chunk = f.read(chunk_size)
            if not chunk:
                break
            chunks.append(chunk)
    
    with ThreadPoolExecutor(max_workers=max_workers) as executor:
        futures = []
        for i, chunk in enumerate(chunks):
            future = executor.submit(upload_chunk, chunk, i, url)
            futures.append(future)
        
        results = [f.result() for f in futures]
    return results

3. 使用aiohttp进行异步上传

import aiohttp
import asyncio

async def async_upload(file_path, url, chunk_size=8192):
    async with aiohttp.ClientSession() as session:
        with open(file_path, 'rb') as f:
            data = aiohttp.FormData()
            data.add_field('file', f, filename=os.path.basename(file_path))
            
            async with session.post(url, data=data) as response:
                return await response.text()

# 使用示例
# asyncio.run(async_upload('large_file.zip', 'https://example.com/upload'))

4. 压缩后再上传(适合文本类文件)

import gzip
import io

def upload_compressed(file_path, url):
    with open(file_path, 'rb') as f:
        original_data = f.read()
    
    # 压缩数据
    compressed = gzip.compress(original_data)
    
    # 使用BytesIO包装压缩数据
    compressed_file = io.BytesIO(compressed)
    
    files = {'file': ('compressed.gz', compressed_file)}
    response = requests.post(url, files=files)
    return response

选择建议:

  • 小文件直接用requests单次上传
  • 大文件用分块+多线程
  • 高并发场景用aiohttp异步
  • 文本文件先压缩再传

一句话总结:根据文件类型和大小选择合适的传输策略,分块和并行是关键。

钱能解决的问题不要动脑子。。。浪费时间

世界加钱可及…

加钱加带宽,上下行对等线路买起来,上传速度就快了,你再怎么优化都被物理速率限制

我想到的两个:
-bbr
-多线程上传,你这个是客户端所以协议自己可以定制哈

LS 几位说的都是玄的。我说个不玄的。

js file slice api + nginx uplod module

多线程上传。错误自动重试。可以保证打满带宽。

没上 gzip 的话就上一下。不过我觉得很可能已经上了。

掉包率高的线路可以考虑一下 QUIC 协议。

上传前压缩是必须的,另外还可以缓存已经处理过的文件,上传前对比是否已经有处理过,有的话直接返回结果,不上传。所谓的秒传就是这么个原理

回到顶部