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
相关产品推荐
相关产品推荐

