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

Flask上传文件到AWS S3出现FileNotFoundError错误如何解决

问题根因

你触发FileNotFoundError的核心原因是:Flask从请求中拿到的上传文件默认是存在内存里的临时对象,你没有把它保存到本地磁盘,就直接尝试用open()读取对应文件名的本地文件,自然会找不到路径。你原来的代码里只调用了secure_filename处理文件名,完全没有执行文件落盘的操作。

同时你的代码还存在msg变量作用域问题:如果没有触发POST请求或者文件校验不通过,msg未定义会直接抛出变量未定义错误。


修复方案

方案1:先将上传文件保存到本地再上传到S3(适合需要本地留存文件的场景)

先调用diag_file.save()把文件存到本地,再进行读取上传即可:

import os
from flask import Flask, request, render_template
import requests
import logging

app = Flask(__name__)
# 提前创建好这个临时存储文件夹,并赋予Flask运行用户读写权限
UPLOAD_FOLDER = './temp_uploads'
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER

@app.route('/upload',methods=['POST'])
def upload():
    msg = ""
    if request.method == 'POST':
        diag_file = request.files.get('file')
        if diag_file and diag_file.filename != '':
            filename = secure_filename(diag_file.filename)
            # 拼接完整的本地存储路径
            local_file_path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
            # 先把文件保存到本地
            diag_file.save(local_file_path)
            
            result = create_presigned_post("bucket123", filename)
            # 读取本地文件上传到S3
            with open(local_file_path, 'rb') as f:
                files = {'file': (filename, f)}
                http_response = requests.post(result['url'], data=result['fields'], files=files)
            
            logging.info(f'File upload HTTP status code: {http_response.status_code}')
            msg = str(create_presigned_url("bucket123", filename))
            
            # 可选:如果不需要本地留存文件,上传到S3后可以删除本地临时文件
            # os.remove(local_file_path)
                
    return render_template("file_upload_to_s3.html", msg=msg)

方案2:直接使用内存中的文件对象上传(推荐,无本地磁盘依赖)

实际上你完全不需要把文件存到本地,Flask的FileStorage对象本身就支持直接读取,不用再走本地文件读写的流程,性能更好也不会出现文件找不到的问题:

@app.route('/upload',methods=['POST'])
def upload():
    msg = ""
    if request.method == 'POST':
        diag_file = request.files.get('file')
        if diag_file and diag_file.filename != '':
            filename = secure_filename(diag_file.filename)
            result = create_presigned_post("bucket123", filename)
            # 直接使用diag_file对象,不需要保存到本地再读取
            files = {'file': (filename, diag_file)}
            http_response = requests.post(result['url'], data=result['fields'], files=files)
            
            logging.info(f'File upload HTTP status code: {http_response.status_code}')
            msg = str(create_presigned_url("bucket123", filename))
                
    return render_template("file_upload_to_s3.html", msg=msg)

额外注意事项

  • 确认create_presigned_post和create_presigned_url函数的权限配置正常,确保生成的预签名URL有对应S3桶的读写权限
  • 如果使用方案1,要确保UPLOAD_FOLDER对应的目录已存在,且运行Flask服务的用户对该目录有读写权限,避免保存文件时报权限错误

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.28 19:54:04