Bootstrap

【Flask项目】文件分享系统(二)

前一篇文章简单分析了基于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模板,欢迎大家的关注!

;