flask文件的上传和下载
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | from werkzeug.utils import secure_filename from flask import Flask,render_template,jsonify,request import time import os import base64 app = Flask(__name__) UPLOAD_FOLDER = 'upload' app.config[ 'UPLOAD_FOLDER' ] = UPLOAD_FOLDER basedir = os.path.abspath(os.path.dirname(__file__)) ALLOWED_EXTENSIONS = set ([ 'txt' , 'png' , 'jpg' , 'xls' , 'JPG' , 'PNG' , 'xlsx' , 'gif' , 'GIF' ]) # 用于判断文件后缀 def allowed_file(filename): return '.' in filename and filename.rsplit( '.' , 1 )[ 1 ] in ALLOWED_EXTENSIONS # 用于测试上传,稍后用到 @app .route( '/test/upload' ) def upload_test(): return render_template( 'upload.html' ) # 上传文件 @app .route( '/api/upload' ,methods = [ 'POST' ],strict_slashes = False ) def api_upload(): file_dir = os.path.join(basedir,app.config[ 'UPLOAD_FOLDER' ]) if not os.path.exists(file_dir): os.makedirs(file_dir) f = request.files[ 'myfile' ] # 从表单的file字段获取文件,myfile为该表单的name值 if f and allowed_file(f.filename): # 判断是否是允许上传的文件类型 fname = secure_filename(f.filename) print fname ext = fname.rsplit( '.' , 1 )[ 1 ] # 获取文件后缀 unix_time = int (time.time()) new_filename = str (unix_time) + '.' + ext # 修改了上传的文件名 f.save(os.path.join(file_dir,new_filename)) #保存文件到upload目录 token = base64.b64encode(new_filename) print token return jsonify({ "errno" : 0 , "errmsg" : "上传成功" , "token" :token}) else : return jsonify({ "errno" : 1001 , "errmsg" : "上传失败" }) if __name__ = = '__main__' : app.run(debug = True ) |
上面我们写了一个上传接口,我们为了测试这个接口是否工作正常,还得写一个页面(upload.html):
1 2 3 4 5 6 | <form id = "form1" method = "post" action = "/api/upload" enctype = "multipart/form-data" > <div> < input id = "File1" type = "file" name = "myfile" / > < input type = "submit" >提交< / input > < / div> < / form> |
好了,页面也写完了,我们运行flask服务后,可以访问到http://127.0.0.1/test/upload
页面,上传文件并提交后,我们的接口会返回如下信息:
1 2 3 4 5 | { "errmsg" : "\u4e0a\u4f20\u6210\u529f" , "errno" : 0 , "token" : "MTQ2MzU4MDc5Mi5KUEc=" } |
同时upload目录中也有了刚上传的文件,表明测试成功。
文件下载
文件下载要比上传简单的多,核心代码如下:
1 2 3 4 5 6 7 8 | from flask import request,jsonify,send_from_directory,abort import os def download(filename): if request.method = = "GET" : if os.path.isfile(os.path.join( 'upload' , filename)): return send_from_directory( 'upload' ,filename,as_attachment = True ) abort( 404 ) |
这里主要需要注意的是send_from_directory方法,经过实测,需加参数as_attachment=True,否则对于图片格式、txt格式,会把文件内容直接显示在浏览器,对于xlsx等格式,虽然会下载,但是下载的文件名也不正确,切记切记
问题:上传过程中,如果文件名是中文 问题未解决
哪位兄弟解决了(文件重命名不算解决)能不能贴上代码
评论区一楼的兄弟:
把该行代码fname = secure_filename(f.filename)替换为 fname = f.filename
这个办法是可以解决,但是这样就缺少了secure_filename方法中的一些验证,
本打算重写这个方法,进行一些验证,但是对于中文应该做何种验证,又无从下手了,有木有有意见的大兄弟。
=================================================================================
码字不易望各位老铁多多支持
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了