flask中request对象以及文件上传详解

request获取请求参数:

from flask import request

与Django不同的是,flask是不需要将request对象作为第一个参数传入视图函数,他的request对象是来自于flask,是一个请求上下文对象(全局变量 --> 线程局部变量,使用起来就像线程全局变量一样,具有较高的隔离性),我们只需导入即可使用,request对象中保存了一次HTTP请求的一切信息。

request原型猜想

request = {
	"线程A"{
		form:
		args:
		data:
	},
	"线程B"{
		form:
		args:
		data:
	},
	...
}
属性说明(类型)
data记录请求的数据,并转换为字符串 (*)
form记录请求中的表单数据 (MultiDict)
args记录请求(url)中的查询参数 (MultiDict)
cookies记录请求中的cookie信息 (Dict)
headers记录请求中的报文头 (EnvironHeaders)
method记录请求使用的HTTP方法 (GET/POST)
url记录请求的url地址 (string)例如:http://127.0.0.1:5000/index
path记录请求路径(string)例如:/index
files记录请求上传的文件 (*)

表单格式的数据,一个类字典的对象,通过request.form.get()方法只能拿到多个同名参数的第一个,要想拿到所有同名的参数,必须使用request.form.getlist()来获取。

from flask import Flask, request

app = Flask(__name__)

@app.route('/index', methods=['POST'])
def index():
    # 从request中获取表单数据,一个类字典的对象
    name = request.form.get('name')
    age = request.form.get('age')
    gender = request.form.get('gender')
    return 'hello name=%s, age=%s, gender=%s' % (name, age)

上传文件示例:

from flask import Flask, request

app = Flask(__name__)

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
	if request.method == 'POST':
		f_obj = request.files['the_file']
		if f_obj is None:
			return '文件未上传'
		# 将文件保存至本地
		# 1.创建一个文件
		f = open('./demo.jpg', 'wb')
		# 2.读取用户上传文件内容,写入本地创建的文件
		data = f_obj.read()
		f.write(data)
		f.close()
		return '上传成功'

flask内部已经将保存文件封装了一个save方法,我们直接调用即可。

from flask import Flask, request

app = Flask(__name__)

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
	if request.method == 'POST':
		f_obj = request.files['the_file']
		if f_obj is None:
			return '文件未上传'
		f_obj.save('./demo.jpg')
		return '上传成功'

文件类型的数据,可以是任何格式,如果你想知道上传前文件在客户端的文件名是什么,你可以访问filename属性,但永远不要信任这个值,这个值是可以伪造的,如果你要把文件按客户端提供的文件名上传至服务器,那么请把它传递给Werkzeug提供的secure_filename()函数。

from flask import request
from werkzeug.utils import secure_filename

@app.route('/upload', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        f = request.files['the_file']
        if f is None:
			return '文件未上传'
        f.save('/var/www/uploads/' + secure_filename(f.filename))
    ...

我们从一个基本的应用开始,这个应用上传文件到一个指定目录,并把文件显示给用户

import os
from flask import Flask, flash, request, redirect, url_for
from werkzeug.utils import secure_filename
from flask import send_from_directory


# 上传文件要储存的目录
UPLOAD_FOLDER = '/path/to/the/uploads'
# 允许上传的文件扩展名的集合,确保用户不能上传html格式文件,防止xss攻击
ALLOWED_EXTENSIONS = set(['txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif'])

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

@app.route('/uploads/<filename>')
def uploaded_file(filename):
	# send_from_directory:使用send_file函数,将指定上传目录中的文件发送到客户端
    return send_from_directory(app.config['UPLOAD_FOLDER'],
                               filename)

@app.route('/', methods=['GET', 'POST'])
def upload_file():
    if request.method == 'POST':
        # 检查POST请求是否包含文件部分
        if 'file' not in request.files:
        	# get_flashed_messages()来获取后台堆积的flash消息
            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):
        	# 获取文件名
            filename = secure_filename(file.filename)
            # 将用户上传文件保存到我们定义好的路径下
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            # 将用户上传文件返回
            return redirect(url_for('uploaded_file',
                                    filename=filename))
                    
	return '''
    <!doctype html>
    <title>Upload new File</title>
    <h1>Upload new File</h1>
    <form method=post enctype=multipart/form-data>
      <input type=file name=file>
      <input type=submit value=Upload>
    </form>
    '''

werkzeug.secure_filename() 说明:

        那么 secure_filename() 函数到底是有什么用?有一条原 则是“永远不要信任用户输入”。这条原则同样适用于已上传文件的文件名。所有提 交的表单数据可能是伪造的,文件名也可以是危险的。此时要谨记:在把文件保存到 文件系统之前总是要使用这个函数对文件名进行安检。

        你可以会好奇 secure_filename() 做了哪些工作,如果 不使用它会有什么后果。假设有人把下面的信息作为 filename 传递给你的应用:

filename = "../../../../home/username/.bashrc"

        假设 ../ 的个数是正确的,你会把它和 UPLOAD_FOLDER 结合在一起,那 么用户就可能有能力修改一个服务器上的文件,这个文件本来是用户无权修改的。 这需要了解应用是如何运行的,但是请相信我,黑客都是很变态的 ?

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

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

改进上传

        Flask 到底是如何处理文件上传的呢?如果上传的文件很小,那么会把它们储存在内 存中。否则就会把它们保存到一个临时的位置(通过 tempfile.gettempdir() 可以得到这个位置)。但是,如何限制上传文件的尺寸呢?缺省情况下, Flask 是 不限制上传文件的尺寸的。可以通过设置配置的 MAX_CONTENT_LENGTH 来限制文 件尺寸:

from flask import Flask, Request

app = Flask(__name__)
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

上面的代码会把尺寸限制为 16 M 。如果上传了大于这个尺寸的文件, Flask 会抛 出一个 RequestEntityTooLarge 异常,我们可以进行捕获。

  • 6
    点赞
  • 29
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
request对象是JSP的内置对象之一,代表了客户端发出的HTTP请求。它提供了一系列的方法,用于获取请求的信息。下面是request对象的所有方法详解: 1. void setAttribute(String name, Object obj):将一个对象绑定到request对象上,并使用指定的名称作为键名。 2. Object getAttribute(String name):根据指定的键名,从request对象上获取绑定的对象。如果没有找到,则返回null。 3. Enumeration<String> getAttributeNames():获取所有绑定到request对象上的对象的名称。 4. String getCharacterEncoding():获取请求的字符编码方式。 5. void setCharacterEncoding(String env):设置请求的字符编码方式。 6. int getContentLength():获取请求的数据长度。 7. String getContentType():获取请求的数据类型。 8. ServletInputStream getInputStream():获取请求的输入流。 9. String getParameter(String name):获取请求指定参数的值。 10. Enumeration<String> getParameterNames():获取请求所有参数的名称。 11. String[] getParameterValues(String name):获取请求指定参数的所有值。 12. Map<String, String[]> getParameterMap():获取请求所有参数的Map集合。 13. String getProtocol():获取请求的协议名称和版本号。 14. String getScheme():获取请求的协议名称。 15. String getServerName():获取请求的服务器名称。 16. int getServerPort():获取请求的服务器端口号。 17. BufferedReader getReader():获取请求的字符输入流。 18. String getRemoteAddr():获取请求的远程IP地址。 19. String getRemoteHost():获取请求的远程主机名。 20. void setAttribute(String name, Object obj, int scope):将一个对象绑定到指定作用域上。 21. Object getAttribute(String name, int scope):根据指定的键名和作用域,从request对象上获取绑定的对象。 22. void removeAttribute(String name):从request对象上移除指定名称的绑定对象。 23. void removeAttribute(String name, int scope):从指定作用域上移除指定名称的绑定对象。 总之,request对象提供了丰富的方法,可以获取请求的各种信息,为开发者提供了非常方便的手段。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值