前一篇文章简单分析了基于Flask的文件分享系统,功能设计的很简单,就是浏览目录,支持文件的上传和下载,那么用flask该如何来实现呢,其实也很简单。
一个Flask程序必须包含实例、路由、视图函数、响应,才能正常运行起来,本文也按这个顺序讲解,如果对Flask是什么不清楚的朋友请去看我写的前几篇关于flask的文章。
实例
生成实例的方式很简单,代码如下
from flask import Flask
app = Flask(__name__, static_folder='./static', template_folder='./templates')
看过我写的《一个完整的Flask程序》一文的朋友可能会发现,这里的Flask实例中还添加了static_folder='./static', template_folder='./templates'
参数,这两个参数是用来指定静态文件和模板文件路径的,指定后,flask会从这两个路径去寻找静态文件和html的模板。
读取目录内容
文件共享系统,首先要实现的就是读取目录内容,并区分出文件和文件夹并返回给浏览器,代码如下
@app.route('/data/')
@app.route('/data/<path:subdir>/')
def index(subdir=''):
if subdir == '':
path = rootdir + 'data'
else:
path = rootdir + 'data' + os.sep + subdir
# 判断如果是文件则下载
if os.path.isfile(path):
return(redirect(url_for('download', filepath=subdir)))
# 显示文件、文件夹,计算文件大小
dirlist = []
filelist = []
for i in os.listdir(path):
if os.path.isdir(path + os.sep + i):
dirlist.append(i + os.sep)
else:
filesize = os.path.getsize(path + os.sep + i)
if (filesize / 1024) > 1000:
filesize = str(round(float(filesize / 1024 /1024),2)) + 'MB'
elif (filesize / 1024) < 1000:
filesize = str(round(float(filesize / 1024),2)) + 'KB'
filelist.append({"name":i, "size":filesize})
return(render_template('index.html', currentpath=subdir, dirlist=dirlist, filelist=filelist))
以上代码中,将目录的浏览和文件的下载和在了一起,如果用户点击的是文件,就跳转到下载的视图函数,如果点击的是目录,则重新读取目录中的内容。
下面来详细解析下代码,前4行用于设置要读取的目录路径,然后判断浏览器传回的路由是否为文件,如果是文件则重定向到下载的视图函数,这里就要引入两个新的知识点,redirect()和url_for()函数,这两个函数是Flask中提供,使用from flask import redirect, url_for
进行导入。
redirect函数用于重定向到另一个URL,它接收一个URL作为参数,然后返回一个重定向的响应对象,浏览器接到重定向的响应后,会重新发起新的URL的请求。这里的URL我们就需要用到url_for函数,这个函数可以让我们通过视图函数的名称和参数生成对应的URL地址。
接下来我们再看后面的代码,dirlist用于存储目录路径,filelist用于存储文件目录路径,后面的for循环用于读取目录下的所有文件和文件夹名称,如果是文件还要计算下文件的大小,然后将目录的路径存到dirlist中,将文件的路径存到filelist中,然后使用render_template渲染网页后返回给浏览器。这里要讲下render_template函数,也是flask提过的一个内部函数,render_template函数用于将HTML模板渲染成最终的HTML页面并返回给用户,其参数就是要渲染的html模板,和html中需要用到的变量,然后render_template函数使用变量在html模板中进行渲染,再返回给用户。使用from flask import render_template
来导入这个函数。
到此,读取目录内容的视图函数就写好了。
下载文件
上面提到,如果传过来的是文件路径,则要重定向到文件下载的视图函数,其代码如下
@app.route('/download/<path:filepath>/')
def download(filepath):
fullpath = rootdir + 'data' + os.sep + filepath
filename = fullpath.split(os.sep)[-1]
dirpath = fullpath[:-len(filename)]
return(send_from_directory(dirpath, filename, as_attachment=True))
从路由中获取到文件路径,然后组成文件是实际的绝对路径,使用send_from_directory函数将文件响应给浏览器,浏览器将会自动下载这个文件。send_from_directory函数也是flask的内置函数,使用from flask import send_from_directory
来导入这个函数。send_from_directory函数接收文件路径和文件名,一定要带上as_attachment=True
参数,告诉浏览器将文件下载到本地,而不打开文件。
这篇文章就先写到这里,下篇文章将文件上传和html模板,欢迎大家的关注!