【Flask】04-上传、会话、上下文、异常、钩子以及信号

工欲善其事,必先利其器。

1.文件上传

用 Flask 处理文件上传很容易,只要确保不要忘记在你的 HTML 表单中设置 enctype="multipart/form-data" 属性就可以了。否则浏览器将不会传送你的文件。

已上传的文件被储存在内存或文件系统的临时位置。你可以通过请求对象 files 属性来访问上传的文件,save()方法用于把上传文件保存到服务器的文件系统中。

文件上传的基本原理实际上很简单,基本上是:

  1. 一个带有 enctype=multipart/form-data标记,标记中含有 一个
  2. 应用通过请求对象的 files 字典来访问文件。
  3. 使用文件的 save()方法把文件 永久地保存在文件系统中。

案例:上传文件到一个指定目录

  • 前端代码



    
    Title


  • 后端代码
import os
from flask import Flask, flash, request, redirect, url_for, render_template
from werkzeug.utils import secure_filename

UPLOAD_FOLDER = os.path.dirname(os.path.abspath(__name__))
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'}

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER
app.config['SECRET_KEY'] = "ahfkkalahp9qnofnovna"
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024 # 尺寸限制为 16 M


def allowed_file(filename):
    # 判断后缀
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route("/upload/", methods=["POST", "GET"])
def upload():
    if request.method == "GET":
        return render_template("upload.html")
    else:
        if 'file' not in request.files: # 判断表单name
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        if file.filename == '': # 判断文件名称
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename): # 判断文件后缀是否符合ALLOWED_EXTENSIONS
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            return "upload ok"

if __name__ == '__main__':
    app.run(debug=True)
  • UPLOAD_FOLDER :是上传文 件要储存的目录。
  • ALLOWED_EXTENSIONS :是允许上传的文件扩展名的集合。
  • MAX_CONTENT_LENGTH:限制文件大小
  • SECRET_KEY:post请求需要配置该参数
  • secure_filename() :假设filename = "../../../../home/username/.bashrc",你会把它和 UPLOAD_FOLDER 结合在一起,那么用户就可能有能力修改一个服务器上的文件,这个文件本来是用户无权修改的

现在来看看函数是如何工作的:

>>> secure_filename('../../../../home/username/.bashrc')
'home_username_.bashrc'

上传扩展 Flask-Uploads

2. 会话

2.1 Cookies

要访问 cookies ,可以使用 cookies属性。可以使用响应 对象 的 set_cookie方法来设置 cookies 。请求对象的 cookies属性是一个包含了客户端传输的所有 cookies 的字典。

  • 读取 cookies
from flask import request

@app.route('/')
def index():
    username = request.cookies.get('username')
  • 储存 cookies
from flask import make_response

@app.route('/')
def index():
    resp = make_response(render_template(...))
    resp.set_cookie('username', 'the username')
    return resp

注意, cookies 设置在响应对象上。通常只是从视图函数返回字符串, Flask 会把它们 转换为响应对象。如果你想显式地转换,那么可以使用 make_response() 函数,然后再修改它。

set_cookie(key,value ='',max_age = None,expires = None,path ='/',domain = None,secure = False,httponly = False,samesite = None)
参数 介绍
key
value
max_age 过期时间,单位秒
expries 过期时间,datetime类型,这个时间需要设置为格林尼治时间,也就是要距离北京少8个小时的时间。
path 表示存储浏览器根目录
domain 设置跨域
secure True表示仅支持HTTPS
httponly 禁止JavaScript访问Cookie。 这是个Cookie标准的扩展,可能不是所有浏览器都支持。
samesite 限制cookie的范围,只能访问当前设置的站点
  • 删除 cookies
   # 源码
    def delete_cookie(self, key, path="/", domain=None):
        """Delete a cookie.  Fails silently if key doesn't exist.

        :param key: the key (name) of the cookie to be deleted.
        :param path: if the cookie that should be deleted was limited to a
                     path, the path has to be defined here.
        :param domain: if the cookie that should be deleted was limited to a
                       domain, that domain has to be defined here.
        """
        self.set_cookie(key, expires=0, max_age=0, path=path, domain=domain)

2.2 Session

除了请求对象之外还有一种称为 session 的对象,允许你在不同请求 之间储存信息。这个对象相当于用密钥签名加密的 cookie ,即用户可以查看你的 cookie ,但是如果没有密钥就无法修改它。

案例:

import os
from flask import session, Flask

app = Flask(__name__)
app.config['SECRET_KEY'] = os.urandom(16)

@app.route("/set-session/")
def set_session():
    session["username"] = "jack"
    return "set session ok"

@app.route("/get-session/")
def get_session():
    username = session.get("username")
    if not username:
        return "get session fail"
    else:
        return username

if __name__ == '__main__':
    app.run(debug=True)
  • 设置 Session
session[key] = value
  • 获取 Session
session[key]
session.get(key)
  • 删除 Session某个键值
session.pop(key)
del session[key]
session.clear() # 清空

Session的设置、获取、删除类似于字典的操作

  • 过期时间
session.permanent=True

如果设置为“ True”,则会话的生存时间为permanent_session_lifetime秒。 默认值为31天。 如果设置为False(默认设置),则当用户关闭浏览器时,会话将被删除。

PERMANENT_SESSION_LIFETIME 配置过期时间,单位:秒

你可能感兴趣的:(【Flask】04-上传、会话、上下文、异常、钩子以及信号)