如何从Flask服务直接上传文件至Minio Bucket(无需本地暂存)
直接从Flask上传文件到MinIO(无需本地存储)
当然可以实现直接上传!你完全不需要先把文件存到本地——Flask的FileStorage对象本身就支持类文件对象的接口,直接就能传给MinIO的put_object方法,既省掉本地存储的步骤,又能提升上传效率、节省磁盘空间。
修改思路
- 移除本地文件保存的冗余代码(
file.save(...)) - 直接使用Flask上传的
FileStorage对象的流(file.stream)作为MinIO的数据源 - 正确获取文件大小(MinIO的
put_object必须传入文件长度参数) - 调整
upload_object函数,让它接收文件流和大小,而非本地文件路径
修改后的完整代码
from flask import Flask, request, flash from werkzeug.utils import secure_filename from minio import Minio from minio.error import ResponseError import os # 初始化MinIO客户端(请替换成你的MinIO服务配置) minioClient = Minio( 'your-minio-server:9000', access_key='your-access-key', secret_key='your-secret-key', secure=False # 根据你的MinIO是否启用HTTPS调整 ) ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', '7z', 'iso'} app = Flask(__name__) def allowed_file(filename): return '.' in filename and \ filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS def upload_object(object_name, file_obj, file_size): try: # 直接通过文件流上传到MinIO result = minioClient.put_object( 'miniotestbucket', object_name, file_obj, file_size ) print(f"文件 {object_name} 上传成功,ETag: {result.etag}") return True except ResponseError as e: print(f"MinIO响应错误: {e}") return False except Exception as e: print(f"上传失败: {e}") return False @app.route('/', methods=['GET','POST']) def upload_file(): if request.method == 'POST': if 'file' not in request.files: flash('No file part') return '未检测到上传文件' file = request.files['file'] if file.filename == '': flash('No selected file') return '错误:未选择文件' if file and allowed_file(file.filename): filename = secure_filename(file.filename) # 获取文件大小:优先用content_length,不可靠时手动计算 if file.content_length: file_size = file.content_length else: # 移动指针到文件末尾获取大小,再重置回开头(否则MinIO会读取空内容) file.seek(0, os.SEEK_END) file_size = file.tell() file.seek(0) # 直接上传到MinIO,无需本地存储 upload_success = upload_object(filename, file.stream, file_size) if upload_success: return '文件已成功存储到MinIO Bucket!' else: return '上传到MinIO失败,请检查服务配置' return ''' <!doctype html> <title>Upload IPS File</title> <h1>Upload IPS File</h1> <form method=post enctype=multipart/form-data> <input type=file name=file> <input type=submit value=Upload> </form> ''' if __name__ == '__main__': app.run(debug=True)
关键细节说明
- 文件流的直接使用:Flask的
request.files['file']是FileStorage实例,它的stream属性是标准的类文件对象,完全满足MinIOput_object对数据源的要求。 - 文件大小的兼容性处理:
file.content_length可能会因为客户端上传时未携带该字段而返回None,所以我们添加了手动计算的兜底方案——通过seek和tell获取文件真实大小,之后必须把指针重置回开头,否则MinIO会从文件末尾开始读取,导致上传空文件。 - 移除本地存储依赖:现在不需要
UPLOAD_FOLDER配置和本地文件保存的步骤,直接跳过即可,减少了代码复杂度和磁盘IO操作。
内容的提问来源于stack exchange,提问作者csymvoul
相关产品推荐
相关产品推荐

