用 Flask 处理文件上传很简单。只要确保你没忘记在 HTML 表单中设置 enctype="multipart/form-data" 属性,不然你的浏览器根本不会发送文件。

已上传的文件存储在内存或是文件系统中一个临时的位置。你可以通过请求对象的 files 属性访问它们。每个上传的文件都会存储在这个字典里。它表现近乎为一个标准的 Python file 对象,但它还有一个 save() 方法,这个方法允许你把文件保存到服务器的文件系统上。

我们以上传图片为例:假设将上传的图片只允许'png'、'jpg'、'jpeg'、'gif' 这四种格式,通过url/upload使用POST上传,上传的图片存放在服务器端的static/uploads目录下。

首先在项目HelloWorld中创建目录static/uploads, 这时候我们的目录结构为:

HelloWorld/
  ├ static/
  │  ├ uploads/
  ├ templates/
  ├ server.py
  ├ client.py

werkzeug库可以判断文件名是否安全

我们安装这个库

pip install werkzeug

server.py代码:

from flask import Flask, request
from werkzeug.utils import secure_filename
import os

app = Flask(__name__)

# 文件上传目录
app.config['UPLOAD_FOLDER'] = 'static/uploads/'
# 支持的文件格式
app.config['ALLOWED_EXTENSIONS'] = {'png', 'jpg', 'jpeg', 'gif'}  # 集合类型


# 判断文件名是否是我们支持的格式
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1] in app.config['ALLOWED_EXTENSIONS']


@app.route('/upload', methods=['POST'])
def upload():
    upload_file = request.files['image']
    if upload_file and allowed_file(upload_file.filename): # 上传前文件在客户端的文件名
        filename = secure_filename(upload_file.filename)
        # 将文件保存到 static/uploads 目录,文件名同上传时使用的文件名
        upload_file.save(os.path.join(app.root_path, app.config['UPLOAD_FOLDER'], filename))
        return 'info is '+request.form.get('info', '')+'. success'
    else:
        return 'failed'


if __name__ == '__main__':
    app.run(port=5000, debug=True)

app.config中的config是字典的子类,可以用来设置自有的配置信息,也可以设置自己的配置信息。

函数allowed_file(filename)用来判断filename是否有后缀以及后缀是否在app.config['ALLOWED_EXTENSIONS']中。

upload_file是上传文件对应的对象。

app.root_path获取server.py所在目录在文件系统中的绝对路径。

upload_file.save(path)用来将upload_file保存在服务器的文件系统中,参数最好是绝对路径。函数os.path.join()用来将使用合适的路径分隔符将路径组合起来。

客户端client.py:

import requests

file_data = {'image': open('flask.jpg', 'rb')}

user_info = {'info': 'flask'}

r = requests.post("http://127.0.0.1:5000/upload", data=user_info, files=file_data)

print(r.text)

运行

我们看到图片已经上传成功了

要控制上产文件的大小,可以设置请求实体的大小,例如:

app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 #16MB

不过,在处理上传文件时候,需要使用try:...except:...。

如果要获取上传文件的内容可以:

file_content = request.files['image'].stream.read()
最后修改:2022 年 12 月 05 日
如果觉得我的文章对你有用,请随意赞赏