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

Flask线程上传文件报错I/O operation on closed file 解决方案咨询

问题解决:Flask异步上传文件到S3报"I/O operation on closed file"错误

问题原因

Flask在请求处理完成(执行return后)会自动回收请求相关资源,包括上传文件的句柄。你把上传逻辑放到子线程后,主线程已经结束请求并关闭了文件,子线程启动时文件已无法读取,因此报错。

修改方案(无需本地存储大文件)

核心思路

将文件内容转存到内存缓冲区中,脱离请求生命周期的限制,让子线程可以安全访问文件内容;同时修正文件对象的获取方式(Flask上传文件需从request.files而非request.form读取)。

修改后的完整代码

from io import BytesIO
from flask import request, redirect, url_for, login_required
from werkzeug.utils import secure_filename
import threading

@application.route('/dashboard', methods=['POST'])
@login_required
def dashboard_post():
    # 从request.files获取上传文件(原代码用request.form是错误的)
    file = request.files.get('input_file')
    if not file:
        # 可根据需求添加错误提示逻辑
        return redirect(url_for('dashboard_upload'))
    
    # 将文件内容写入内存缓冲区
    file_buffer = BytesIO()
    file.save(file_buffer)
    # 重置缓冲区指针到起始位置,确保后续读取完整内容
    file_buffer.seek(0)
    filename = secure_filename(file.filename)
    
    # 启动子线程,传入内存缓冲区和文件名
    worker_thread = threading.Thread(target=upload_file, args=[file_buffer, filename])
    worker_thread.start()

    return redirect(url_for('dashboard_upload'))


def upload_file(file_buffer, filename):
    try:
        S3_CLIENT.upload_fileobj(
            file_buffer,
            '<bucketname>',  # 替换为你的实际存储桶名称
            filename,
        )
        print(f"文件 {filename} 已成功上传至S3")
    except Exception as e:
        print(f"S3上传失败: {str(e)}")

关键修改点说明

  • 修正文件获取源:上传文件属于multipart/form-data类型,必须从request.files中获取,原代码的request.form.get无法正确拿到文件对象。
  • 内存缓冲区中转:用BytesIO在内存中存储文件内容,脱离请求生命周期的限制,子线程可安全读取。
  • 重置缓冲区指针:调用file.save()后缓冲区指针会移至末尾,seek(0)确保upload_fileobj能从开头读取完整内容。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 09:25:19