如何用Flask处理文件上传
Flask是一个用Python构建的轻量级或微型Web框架,有助于创建Web应用程序。它提供了有用的工具和功能,使构建网络应用更容易。Flask是可扩展的,在开始使用之前不强制要求特定的结构或要求复杂的模板代码。它为开发者提供了灵活性。
简介
网络应用程序的一个重要特征是能够让用户上传文件。这些文件可以是图片、PDF、音频CSV等。在这篇文章中,我们将看看如何设置一个基本的flask应用,让用户上传文件。
前提条件
通过本指南,我们假设读者具有Python编程语言、HTML的基本知识,并且他们必须具有flask的基本知识;尽管本指南对初学者友好。
在本指南中,我们将使用Python 3和VS Code文本编辑器,你可以下载vscode和Python。
目标
我们将建立一个flask应用程序,使用户能够上传文件到服务器。在本指南的最后,读者将熟悉。
- 创建一个虚拟环境
- 激活一个虚拟环境
- 设置一个flask应用
- 启用文件上传
Python 虚拟环境
虚拟环境是Python项目的一个孤立的环境。有一个由Python创建的叫做venv的模块,它给开发者提供了一个独特的环境,能够安装所有对特定项目来说是独一无二的软件包。
虚拟环境并不改变系统中默认的Python版本或默认安装的软件包,相反,它让你不受系统中安装的其他软件包的干扰。这使得在任何计算机上运行任何Python项目都很容易,而不管系统中安装的Python版本或包是什么。
如何创建一个虚拟环境
创建虚拟环境的过程根据操作系统的不同而不同。在本指南中,我们将从windows操作系统的角度来看这个过程。
首先,在Windows设备上打开PowerShell,使用下面的命令建立一个目录。
mkdir
使用cd directory-name 进入新目录,然后使用命令安装虚拟环境。
pip install virtualenv
然后使用命令创建虚拟环境。
virtualenv myenv
注意,myenv 是我的虚拟环境的名称,它可以是你希望的任何名称。接下来,用命令激活虚拟环境。
myenv/Scripts/activate
如果你使用的是命令行界面(CMD),你的命令将如下所示。
myenv\Scripts\activate.bat
创建我们的项目
在激活了我们的虚拟环境之后,我们现在可以创建我们的项目。要做到这一点,我们将为该项目创建一个新的目录。
使用下面的命令。
mkdir tutorial
注意:
tutorial是我项目的名称。你可以给你的项目起任何你喜欢的名字。要建立一个flask应用程序,我们必须首先安装flask。
要做到这一点,我们将使用下面的命令。
pip install flask
安装完成后,我们将创建一个新文件,名称为app.py ,用下面的代码更新该文件。
from flask import Flask
app = Flask(__name__)
@app.route('/')
def index():
return"hello world"
if __name__==('__main__'):
app.run(debug=True)
从上面的代码中,我们正在从我们安装的flask库中导入flask。
@app.route 是为我们做路由的。
index() 是我们的视图函数,它将把我们的页面内容返回给浏览器。
if语句返回app.run ,这将使我们能够运行我们的应用程序,然后在我们保存更改时刷新我们的页面。为了运行我们的应用程序,我们在终端上运行下面的命令。
python app.py
请注意,app.py 是我的应用程序的名称,你的名称可能不同。如果一切顺利,你将得到如下所示的结果。
为了上传文件,我们将使用WTforms 和flask-uploads 库。为了使用这些库,我们需要安装它们。
用下面的命令来做。
pip install flask_wtf, WTForms
pip install flask-uploads
安装完成后,我们将创建一个文件字段,将代码更新为以下代码。
from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import FileField
app = Flask(__name__)
class MyForm(FlaskForm):
image = FileField('image')
@app.route('/')
def index():
form = MyForm()
return render_template('index.html')
if __name__==('__main__'):
app.run(debug=True)
从上面的代码中,我们首先从flask_wtf 中导入FlaskForm ,从wtforms 中导入FileField 。接下来,我们为我们的表单创建了一个类,因为Myform image是我们的图像文件将被保存到的文件字段。我们在index function 中调用我们的Form类。我们把我们的render 改为render template 。
这也是一个用于渲染HTML模板的flask库。从代码中我们渲染了index.html 。当我们在Flask中使用render_template时,我们创建了一个叫做templates的文件夹,在那里我们存储HTML文件。现在让我们在templates文件夹中创建我们要渲染的HTML模板。
用下面的代码更新HTML文件。
!doctype html>
<html>
<head>
<title>File Upload</title>
</head>
<body>
<form action="/" method="POST" enctype="multipart/form-data">
{{ form.csrf_token }}
{{ form.image }}
<button type="submit">upload</button>
</form>
</body>
</html>
从上面的代码来看,我们的表单需要一个方法POST ,因为我们将发布一个文件。csrf_token 是一个内置的函数,为我们处理安全问题,然后我们使用form.image ,调用我们在Form Class 中创建的表单字段。现在我们可以使用python app.py 来运行我们的应用程序。如果一切都正确,你会得到一个运行时错误,就像下面的图片一样。
只要你试图使用csrf_token ,而不在你的项目文件中添加secret_key ,就会出现这个错误。让我们在我们的代码中添加一个secret key 。
将你的代码更新为下面的代码。
from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import FileField
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
class MyForm(FlaskForm):
image = FileField('image')
@app.route('/')
def index():
form = MyForm()
return render_template('index.html')
if __name__==('__main__'):
app.run(debug=True)
secret_key 可以是任何你想要的东西。
让我们把我们的代码更新为下面的代码。
from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import FileField
app = Flask(__name__)
app.config['SECRET_KEY'] = 'mysecretkey'
class MyForm(FlaskForm):
image = FileField('image')
@app.route('/')
def index():
form = MyForm()
return render_template('index.html', form = form)
if __name__==('__main__'):
app.run(debug=True)
我们的页面现在应该看起来像下面的图片。
从上面的代码来看,form=form ,这样我们的表单就可以显示在我们的HTML页面上。如果我们试图上传图片,我们会遇到另一个错误,如下图所示。
当我们没有给我们的route 指定一个方法时,这个错误经常被抛出。为了解决这个问题,我们将在我们的路由中添加下面的代码。
@app.route('/', methods=['GET', 'POST'])
添加上述代码后,我们的上传将工作,但它不会被保存,因为我们没有给它一个保存的路径。这就是flask uploads 的作用。
让我们使用命令导入flask-uploads 。
from flask_uploads import configure_uploads, IMAGES, UploadSet
configure_uploads 使我们能够设置图片的保存路径, 是我们要上传的文件类型。IMAGES
我们将更新我们的代码:app.config['UPLOADED_IMAGES_DEST'] = 'uploads/images ,这将设置图片保存的文件路径,images = UploadSet('images', IMAGES) 和configure_uploads(app, images) 保存文件扩展名并配置上传。
if form.validate_on_submit():
filename = images.save(form.image.data)
return f'Filename: {filename}'
return render_template('index.html', form = form)
上述片段将验证并保存我们的图像文件。
我们的最终代码将看起来像下面这样。
from flask import Flask, render_template
from flask_wtf import FlaskForm
from wtforms import FileField
from flask_uploads import configure_uploads, IMAGES, UploadSet
app = Flask(__name__)
app.config['SECRET_KEY'] = 'thisisasecret'
app.config['UPLOADED_IMAGES_DEST'] = 'uploads/images'
images = UploadSet('images', IMAGES)
configure_uploads(app, images)
class MyForm(FlaskForm):
image = FileField('image')
@app.route('/', methods=['GET', 'POST'])
def index():
form = MyForm()
if form.validate_on_submit():
filename = images.save(form.image.data)
return f'Filename: {filename}'
return render_template('index.html', form = form)
if __name__==('__main__'):
app.run(debug=True)
上传文件后,文件名将被返回,如下图所示。
结论
现在我们可以上传图片了。要上传其他类型的文件,我们需要做的就是通过flask上传导入它们,配置它们的目标路径,并指定它们的文件扩展。