如何用flask创建动态文件发送算法
How to create dynamic file sending algorithm with flask
我在使用 Flask 提供文件时遇到了一些问题。
首先是我的文件树:
processedMain
--processed1
--processed2
--...
--processedN
在每个文件夹中,我都有一堆文件,我在 table 中表示所有这些文件,我将 href link 与每个文件的路径放在一起,并使用 [=45= 通过路由函数传递它] return.
问题是我能够让它工作的唯一方法是为每个硬编码的子文件夹创建@app.route,如下所示:
@app.route('/' + pathFits1[1] + '<id>', methods=['GET'])
def returnImg1(id):
return send_file(pathFits1[1] + id, as_attachment=True, attachment_filename=id)
@app.route('/' + pathFits1[2] +'<id>', methods=['GET'])
def returnImg2(id):
return send_file(pathFits1[2] + id, as_attachment=True, attachment_filename=id)
@app.route('/' + pathFits1[3] + '<id>', methods=['GET'])
def returnImg3(id):
return send_file(pathFits1[3] + id, as_attachment=True, attachment_filename=id)
其中 pathFits1[i] 是子文件夹的路径,当用户在网络中单击文件时传递 id table。
问题是我有很多子文件夹,为每个子文件夹创建@app.route 很累人。
是否可以为每件事只创建一条路线?
P.S。
我对flask还很陌生,所以如果我忘了说什么,请告诉我,我会补上的。
解决方案
其实很简单。
正如@Dan.D 指出的那样,flask 具有捕获变量的转换器,对我来说这就是我所需要的,因为我的 id 变量已经包含文件的完整路径。
所以现在只有这 3 行替代了一大堆或重复的代码:
@app.route('/<path:id>')
def returnImg(id):
fileName = id.rsplit('/', 1)[-1]
return send_file(id, as_attachment=True, attachment_filename=fileName)
其中 id 是文件的完整路径,path: 是路径的转换器,fileName 是用户将下载的文件的名称,其中没有路径(所有内容都在最后一个斜杠之后)
您可以捕获路由表达式中的路径。来自文档:
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return 'Subpath %s' % subpath
据我所知,Flask 不支持 @app.route
URL 中的多个可变部分。但是,您可以将文件的完整路径设置为可变部分,然后解析它以提取子文件夹路径和文件 ID。
这是一个工作示例:
pathFits1 = [None] * 3
pathFits1[1] = 'content/images1/'
pathFits1[2] = 'content/images2/'
@app.route('/<path:fullpath>', methods=['GET'])
def returnImg(fullpath):
global pathFits1
print("--> GET request: ", fullpath)
# parse the full path to extract the subpath and ID
# subpath: get everything until the last slash
subpath = fullpath.rsplit('/', 1)[:-1][0] + '/'
# id: get string after the last slash
id = fullpath.rsplit('/', 1)[-1]
print("ID:", id, "\tsubpath:", subpath)
# try to send the file if the subpath is valid
if subpath in pathFits1:
print("valid path, attempting to sending file")
try:
return send_file(subpath + id, as_attachment=True, attachment_filename=id)
except Exception as e:
print(e)
return "file not found"
return "invalid path"
但是,更好的实现方式是将文件 ID 和路径作为 GET 请求参数发送(例如 http://127.0.0.1:8000/returnimg?id=3&path=content/images1/
)并像这样检索它们:
from flask import Flask, send_file, request
app = Flask(__name__)
pathFits1 = [None] * 3
pathFits1[1] = 'content/images1/'
pathFits1[2] = 'content/images2/'
@app.route('/returnimg', methods=['GET'])
def returnImg():
global pathFits1
id = request.args.get('id')
path = request.args.get('path')
print("ID:", id, "\tpath:", path)
# try to send the file if the subpath is valid
if path in pathFits1:
print("valid path, attempting to sending file")
try:
return send_file(path + id, as_attachment=True, attachment_filename=id)
except Exception as e:
print(e)
return "file not found"
return "invalid path"
我在使用 Flask 提供文件时遇到了一些问题。
首先是我的文件树:
processedMain
--processed1
--processed2
--...
--processedN
在每个文件夹中,我都有一堆文件,我在 table 中表示所有这些文件,我将 href link 与每个文件的路径放在一起,并使用 [=45= 通过路由函数传递它] return.
问题是我能够让它工作的唯一方法是为每个硬编码的子文件夹创建@app.route,如下所示:
@app.route('/' + pathFits1[1] + '<id>', methods=['GET'])
def returnImg1(id):
return send_file(pathFits1[1] + id, as_attachment=True, attachment_filename=id)
@app.route('/' + pathFits1[2] +'<id>', methods=['GET'])
def returnImg2(id):
return send_file(pathFits1[2] + id, as_attachment=True, attachment_filename=id)
@app.route('/' + pathFits1[3] + '<id>', methods=['GET'])
def returnImg3(id):
return send_file(pathFits1[3] + id, as_attachment=True, attachment_filename=id)
其中 pathFits1[i] 是子文件夹的路径,当用户在网络中单击文件时传递 id table。
问题是我有很多子文件夹,为每个子文件夹创建@app.route 很累人。 是否可以为每件事只创建一条路线?
P.S。 我对flask还很陌生,所以如果我忘了说什么,请告诉我,我会补上的。
解决方案
其实很简单。 正如@Dan.D 指出的那样,flask 具有捕获变量的转换器,对我来说这就是我所需要的,因为我的 id 变量已经包含文件的完整路径。 所以现在只有这 3 行替代了一大堆或重复的代码:
@app.route('/<path:id>')
def returnImg(id):
fileName = id.rsplit('/', 1)[-1]
return send_file(id, as_attachment=True, attachment_filename=fileName)
其中 id 是文件的完整路径,path: 是路径的转换器,fileName 是用户将下载的文件的名称,其中没有路径(所有内容都在最后一个斜杠之后)
您可以捕获路由表达式中的路径。来自文档:
@app.route('/path/<path:subpath>')
def show_subpath(subpath):
# show the subpath after /path/
return 'Subpath %s' % subpath
据我所知,Flask 不支持 @app.route
URL 中的多个可变部分。但是,您可以将文件的完整路径设置为可变部分,然后解析它以提取子文件夹路径和文件 ID。
这是一个工作示例:
pathFits1 = [None] * 3
pathFits1[1] = 'content/images1/'
pathFits1[2] = 'content/images2/'
@app.route('/<path:fullpath>', methods=['GET'])
def returnImg(fullpath):
global pathFits1
print("--> GET request: ", fullpath)
# parse the full path to extract the subpath and ID
# subpath: get everything until the last slash
subpath = fullpath.rsplit('/', 1)[:-1][0] + '/'
# id: get string after the last slash
id = fullpath.rsplit('/', 1)[-1]
print("ID:", id, "\tsubpath:", subpath)
# try to send the file if the subpath is valid
if subpath in pathFits1:
print("valid path, attempting to sending file")
try:
return send_file(subpath + id, as_attachment=True, attachment_filename=id)
except Exception as e:
print(e)
return "file not found"
return "invalid path"
但是,更好的实现方式是将文件 ID 和路径作为 GET 请求参数发送(例如 http://127.0.0.1:8000/returnimg?id=3&path=content/images1/
)并像这样检索它们:
from flask import Flask, send_file, request
app = Flask(__name__)
pathFits1 = [None] * 3
pathFits1[1] = 'content/images1/'
pathFits1[2] = 'content/images2/'
@app.route('/returnimg', methods=['GET'])
def returnImg():
global pathFits1
id = request.args.get('id')
path = request.args.get('path')
print("ID:", id, "\tpath:", path)
# try to send the file if the subpath is valid
if path in pathFits1:
print("valid path, attempting to sending file")
try:
return send_file(path + id, as_attachment=True, attachment_filename=id)
except Exception as e:
print(e)
return "file not found"
return "invalid path"