如何用Python实现超出RAM容量的大文件低内存HTTP上传
curl低内存传输大文件的实现原理
curl之所以能在极低内存占用下传输远大于内存的文件,核心是采用了流式分块传输的设计,没有一次性加载全量文件到内存:
- 默认使用HTTP协议的
Transfer-Encoding: chunked扩展头,不需要提前计算并声明整个文件的Content-Length,而是将文件拆分为若干个大小固定的小数据块(通常为几KB到几十KB),读取一块发送一块,发送完成后立即释放当前块的内存,内存占用不会随文件大小增长。 - 底层调用操作系统的零拷贝API(如Linux的sendfile系统调用),文件数据无需从内核态拷贝到用户态就能直接发送到网卡,用户态的内存占用可以稳定在几MB级别,哪怕传输几十GB的文件也不会占用过多内存。
- 全程仅使用固定大小的缓冲区循环读写,没有多余的全量数据拷贝逻辑。
你之前用Python触发内存限制,绝大多数情况是代码里一次性读取了整个文件到内存(比如调用了f.read()将全量文件内容存到变量,或是将文件内容全量拼接成请求体后再发送),2GB的文件内容直接放到1GB内存的VPS上运行自然会触发OOM。
低内存实现HTTP POST发送超大文件的方法
只要遵循流式传输的思路,Python完全可以做到和curl一样的低内存占用,下面是两种常用的实现方案:
基于requests库实现(最简方案)
requests原生支持流式上传,只需将文件对象直接传入接口即可,无需手动处理分块逻辑:
import requests # 以二进制只读模式打开文件,不要调用read()读取全量内容 with open("your_large_file", "rb") as f: # 直接传入文件对象,requests会自动使用分块传输逻辑 response = requests.post("https://target-domain.com/upload", data=f) print(response.status_code)
如果服务端要求multipart/form-data格式的上传,调整参数即可,requests同样会做流式处理:
import requests with open("your_large_file", "rb") as f: response = requests.post( "https://target-domain.com/upload", files={"upload_file": f} )
这种方案的内存占用可以稳定在10MB以内,完全支持传输几十GB级别的文件。
基于Python标准库实现(无第三方依赖)
如果环境无法安装第三方库,用内置的http.client也可以实现流式传输:
from http.client import HTTPSConnection import os file_path = "your_large_file" # 提前获取文件大小,也可以改用分块传输不声明Content-Length file_size = os.path.getsize(file_path) conn = HTTPSConnection("target-domain.com") conn.putrequest("POST", "/upload") conn.putheader("Content-Type", "application/octet-stream") conn.putheader("Content-Length", str(file_size)) conn.endheaders() # 每次读取8KB内容发送,读完即释放 with open(file_path, "rb") as f: while chunk := f.read(8192): conn.send(chunk) response = conn.getresponse() print(response.status) conn.close()
内容的提问来源于stack exchange,提问作者yasser karimi
相关产品推荐
相关产品推荐

