Flask上传文件
Posted Flask学习笔记
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Flask上传文件相关的知识,希望对你有一定的参考价值。
Flask上传文件
上传文件包括很多,比如用户头像,文章图片,文件分享等等,它也涉及到很多内容:上传文件,过滤文件类型,限制大小,文件名的编辑,拖拽上传,进度条,文件命名,文件目录的管理等等.
文件上传的基本概念非常简单:
一个在 html
文档中定义的好的form
标签(<from enctype=multipart/form-data>
),并且form
中必须包含一个<input type=file>
标签服务端应用通过请求对象上的 request.files
字典访问文件.使用文件对象的 save()
方法将文件永久的保存在文件系统中.
示例代码
https://github.com/ningwenyan/demo_code/tree/master/flask_demo_code/T14
1.flask
原生文件上传
目录结构
file_upload_1
├── app.py # 主程序
├── config.py # 配置文件
├── static # css,js文件
├── templates # 渲染模板文件
│ └── uploads.html # 上传html文件
└── uploads # 上传文件的文件夹
uploads.html
实现一个简单的上传功能,需要注意的是,必须写enctype="multipart/form-data
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>上传</title>
</head>
<body>
<form action="" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>上传文件</td>
<td><input type="file" name="file"></td>
</tr>
<tr>
<td><label for="#"><input type="submit"></label></td>
</tr>
</table>
</form>
</body>
</html>
config.py
import os
DEBUG=True
TEMPLATES_AUTO_RELOAD=True
par_dir = os.path.dirname(__file__)
UPLOAD_FOLDER=par_dir+'/uploads/' # 指定要上传的文件夹
MAX_CONTENT_LENGTH=16*1024*1024 # 指定上传的文件的最大大小
app.py
from flask import Flask
import config
from flask import request,render_template,send_from_directory
from werkzeug.utils import secure_filename
import os
app = Flask(__name__)
app.config.from_object(config)
@app.route('/')
def hello_world():
return 'Hello World!'
ALLOWED_EXTENSIONS = set(['txt','pdf','png','jpg','jpeg','gif'])
# 判断文件后缀
def allowed_file(filename):
return '.' in filename and filename.rsplit('.',1)[1] in ALLOWED_EXTENSIONS
# 定义上传文件路由
@app.route('/uploads/',methods=['GET','POST'])
def upload_file():
if request.method == 'GET':
return render_template('uploads.html')
else:
# 文件类型不能用 request.form.get() 获取
# 要使用 request.files.get() 方法
file = request.files.get('file')
# 可以通过 文件对象的 filename 属性拿到文件名
if file and allowed_file(file.filename):
# 出于安全考虑,使用 security filename
filename = secure_filename(file.filename)
print(app.config['UPLOAD_FOLDER'])
file.save(os.path.join(app.config['UPLOAD_FOLDER'],filename))
return render_template('uploads.html')
# 定义访问上传文件路径
@app.route('/uploads/<filename>')
def uploads_file(filename):
# 调用 send_from_directory 方法提供对已上传文件的访问服务
return send_from_directory(app.config['UPLOAD_FOLDER'],filename)
if __name__ == '__main__':
app.run()需要注意的是:
必须手动验证上传的文件后缀,不符合的不上传 使用 request.file.get()
方法获取文件,而不是request.form.get()
,虽然文件处于表单中,但是文件定义在另外的方法中file.save()
方法来指定保存文件的最终路径使用 security_filename
来处理文件名,不能相信用户上传的任何东西可以定义回显来上传的文件,这个需要 send_from_directory
方法的支持.
2.Flask-Uploads
Flask-Uploads
简化加强了flask
的原生上传功能.
Flask-Uploads
中有一个UploadSet
的概念,用他来统一验证要上传的文件类型,以及文件名称的安全问题.
1.安装
$ pip install flask-upload
2.基本概念
文件类型过滤 设置文件上传的路径和文件类型:(在
config.py
文件中指定)
UPLOADED_FILES_DEST
: 指定上传文件保存路径UPLOADED_FILES_URL
:指定上传文件的URLUPLOADED_FILES_ALLOW:指定允许上传的文件
UPLOAD_FILES_DENY
:指定不允许上传的文件注意:
Flask-Uploads
可以设置不同的set
,所以以上FILES
的名称不是绝对的,而是指定UploadSet(name='FILES')
的name
字段.这个名称可以根据自己上传文件的不同,而指定不同的名称,比如:如果是图片可以随意命名.# config.py
UPLOADED_IMG_DEST=xxx
UPLOADED_IMG_ALLOW=tuple('jpg jpe jpeg png gif svg bmp'.split())
# app.py
UploadSet(name='IMG')
UPLOADED_IMG_ALLOW=tuple('jpg jpe jpeg png gif svg bmp'.split())
是自定义的文件类型的集合,也就是说,自定义文件类型必须是tuple
类型,而且必须是以上格式.
Flask-Uploads
中也有一些内置的类型:TEXT = ('txt',)
DOCUMENTS = tuple('rtf odf ods gnumeric abw doc docx xls xlsx'.split())
IMAGES = tuple('jpg jpe jpeg png gif svg bmp'.split())
AUDIO = tuple('wav mp3 aac ogg oga flac'.split())
DATA = tuple('csv ini json plist xml yaml yml'.split())
SCRIPTS = tuple('js php pl py rb sh'.split())
ARCHIVES = tuple('gz bz2 zip tar tgz txz 7z'.split())
EXECUTABLES = tuple('so exe dll'.split())
DEFAULTS = TEXT + DOCUMENTS + IMAGES + DATA通过导入即可使用,已经可以满足基本的使用.
from flask_uploads import TEXT,DOCUTMENTS,...
如果对内置的类型中有些文件不允许上传,可以使用 UPLOADED_X_DENY
来拒绝使用.如果要指定多种类型,可以使用 UPLOADED_IMG_ALLOW=(IMGAGE+DOCUMENTS)
来扩展
文件名隐患 不用使用
secure_filename()
来处理文件名,直接使用UploadSet().save(request.files.get('photo'))
方法来安全保存文件.photo
是input
标签的name
元素.
限制文件大小 from flask_uploads import UploadSet,configure_uploads,patch_request_class
patch_request_class(app,32*1024*1024)使用
patch_request_class()
函数绑定app
来限制大小.
获取文件
UploadSet().url(filename)
函数可以获取上传文件的URL
路径,
3.UploadSet()
Flask-Uploads
的核心类UploadSet(name='files', extensions=('txt', 'rtf', 'odf', 'ods', 'gnumeric', 'abw', 'doc', 'docx', 'xls', 'xlsx', 'jpg', 'jpe', 'jpeg', 'png', 'gif', 'svg', 'bmp', 'csv', 'ini', 'json', 'plist', 'xml', 'yaml', 'yml'), default_dest=None)
photos = UploadSet('PHOTO')它包含3个参数
name
:指定文件上传Set
的集合,需要配合config.py
文件中的UPLOADED_X_DEST
的X
字段extensions
:指定上传类型,可以被config.py
中的UPLOADED_X_ALLOW
和UPLOADED_X_DENY
覆盖.default_dest
:指定上传的路径,可以被config.py
中的UPLOADED_X_DEST
覆盖注册配置好的
UploadSet()
要使用方法config_uploads(app, photos)
4.Demo
- END -$ tree
file_upload_2
├── app.py
├── config.py
├── static
├── templates
│ ├── show.html
│ └── upload.html
└── uploads
└── test.doc
upload.html
<form action="" method="post" enctype="multipart/form-data">
<table>
<tr>
<td>上传文件</td>
<td><input type="file" name="photo"></td>
</tr>
<tr>
<td><label for="#"><input type="submit"></label></td>
</tr>
</table>
</form>
show.html
<img src="{{ url }}" alt="{{ name }}">
config.py
import os
from flask_uploads import IMAGES,DOCUMENTS
DEBUG=True
TEMPLATES_AUTO_RELOAD=True
Dir = os.path.dirname(os.path.abspath(__file__))
# 指定上传目录
UPLOADED_PHOTO_DEST=Dir+'/uploads/'
# 指定运行文件类型
# IMAGES = tuple('jpg jpe jpeg png gif svg bmp'.split())
UPLOADED_PHOTO_ALLOW=(IMAGES+DOCUMENTS)
app.py
from flask import Flask,request,redirect,url_for,render_template,abort
from flask_uploads import UploadSet,configure_uploads,patch_request_class
import config
app = Flask(__name__)
app.config.from_object(config)
@app.route('/')
def hello_world():
return 'Hello World!'
# 限定上传文件大小
patch_request_class(app,32*1024*1024)
# 约束上传文件类型和位置
photos = UploadSet('PHOTO')
# 注册到app中
configure_uploads(app, photos)
@app.route('/uploads/',methods=['GET','POST'])
def upload():
if request.method == 'POST' and 'photo' in request.files:
filename = photos.save(request.files.get('photo'))
return redirect(url_for('show',name=filename))
return render_template('upload.html')
@app.route('/uploads/<name>',methods=['GET','POST'])
def show(name):
if name is None:
return abort(404)
# 通过url 方法获取到文件的 URL路径
url = photos.url(name)
return render_template('show.html',url=url,name=name)
if __name__ == '__main__':
app.run()
以上是关于Flask上传文件的主要内容,如果未能解决你的问题,请参考以下文章
如何在Python框架Flask中将图像文件从表单上传到数据库