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

无需预签名URL:Flask API传大文件至S3内存过高的解决办法

解决Flask API上传大文件到S3的内存占用过高问题

核心问题分析

Flask默认会把完整请求体加载到内存中,哪怕用upload_fileobj,如果没调整请求处理逻辑,文件数据还是会先存进内存,导致大文件上传时内存被占满。你的TransferConfig没起作用,本质是文件已经被Flask预加载到内存,boto3的分片配置无法改变这个前提。

解决方案步骤

1. 配置Flask禁用请求体预加载

修改Flask应用配置,避免自动把请求体读进内存,直接处理流式数据:

from flask import Flask, request

app = Flask(__name__)
# 不限制请求大小(按需调整为具体最大值)
app.config['MAX_CONTENT_LENGTH'] = 0
# 避免异常时保留上下文,减少内存占用
app.config['PRESERVE_CONTEXT_ON_EXCEPTION'] = False

2. 直接流式传输请求体到S3

不要用Flask的request.files(它会把文件存到内存或临时文件),直接读取request.stream传给boto3,同时配合优化后的TransferConfig:

import boto3
from boto3.s3.transfer import TransferConfig

s3_client = boto3.client('s3')

@app.route('/upload', methods=['POST', 'PUT'])
def upload_to_s3():
    bucket_name = '你的存储桶名称'
    # 从请求头或参数获取对象键,按需调整
    object_key = request.headers.get('X-Object-Key')
    
    transfer_config = TransferConfig(
        multipart_threshold=100*1024*1024,  # 100MB以上启用分片
        multipart_chunksize=25*1024*1024,   # 每个分片25MB
        use_threads=True,
        max_concurrency=5,  # 降低并发数,减少内存开销
        io_chunksize=1*1024*1024  # 每次读取1MB数据
    )
    
    try:
        # 直接将请求流传给S3,不缓存到内存
        s3_client.upload_fileobj(
            Fileobj=request.stream,
            Bucket=bucket_name,
            Key=object_key,
            Config=transfer_config
        )
        return {'status': 'success'}, 200
    except Exception as e:
        return {'error': str(e)}, 500

3. 额外优化建议

  • 要求客户端发送正确的Content-Length请求头,避免S3上传时出现异常;若使用分块传输编码,boto3也能兼容,但需确保请求格式正确。
  • 不要将文件保存到本地临时目录,保持全程流式传输是最优方案。
  • 调整Kubernetes Pod的内存请求和限制作为兜底,但优先通过代码优化减少内存占用。

为什么之前的TransferConfig没效果?

因为Flask已经把整个文件读进内存,upload_fileobj读取的是内存中的文件对象,而非流式的请求体,所以分片配置无法发挥作用。只有当Fileobj是真正的流式对象(比如request.stream)时,boto3才会按配置的块大小读取数据,不会一次性加载全部内容到内存。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.22 16:38:15