自学内容网 自学内容网

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

上篇文章【Flask项目】文件分享系统(二)中介绍了如何读取目录内容和下载文件,这篇继续讲上传文件和HTML模板。

上传文件

上传文件即用户在浏览器上选择要上传的文件,然后调用上传接口把文件传到flask程序,在看代码前,要先了解一个知识点,那就是请求,什么是请求呢?

请求就是浏览器向flask程序发起访问,告诉flask程序,我想要认识你,flask程序说好呀,欢迎你来和我交流,但是你得和我用同样的语言交流,不然我听不懂。就这样,浏览器必须使用GET、POST、PUT、DELETE等方法和flask程序进行交流,而其中常用的方法就是GET和POST。这里GET和POST方法的区别不做过多讲解了,大家可以看我写的相关文章或去度娘一下,当然,要想快速检索可以考虑AI搜索。这里大家简单的理解为GET只能携带有限的明文参数访问flask程序,而POST可以以非明文的方式携带的内容更多。

当然请求中不光有请求方法,还包括URL、请求头等一些内容,想详细了解的,可以给我留言,我会整理出来一篇详细的文章讲解。简单了解了请求后,我们可以知道,上传文件可以使用POST的方法,携带的数据量大,确相对GET安全一些。

再回到flask程序中,我们如何让其支持POST?又如何从请求中拿到文件内容呢?这个后面来讲,先来看下上传文件的代码。

@app.route('/upload/', methods=['GET', 'POST'])
def upload():
    if request.method == 'POST':
        file = request.files['file']
        if file:
            filename = secure_filename(file.filename)
            print(filename)
            if os.path.exists(rootdir + 'data' + os.sep + filename):
                filename = str(int(time.time())) + '_' + filename
            file.save(os.path.join(rootdir + 'data', filename))
            return('文件上传成功')
    else:
        return('报错啦!!!!')

从上面的代码可以看到,定义路由的地方@app.route('/upload/', methods=['GET', 'POST']),我们加了个参数methods,这个参数就是指定访问该路由可以使用的方法嘀。

我们还可能看到,上传的视图函数中,我们用到了request,英文好的同学应该能知道,这个词有请求的意思,没错这个就是获取浏览器发来的请求嘀。request可不是我们自己定义的变量,而是flask中自带的全局变量,使用from flask import request来导入这个函数。

后面的代码就是判断当前文件是否存在的,如果存在则给他文件名上加个时间,如果不存在则直接保存这个文件。这里为了保证文件名的合法性我使用了werkzeug中的secure_filename函数,使用from werkzeug.utils import secure_filename来导入,这个函数可以保证文件名中不会有特殊字符,造成保存文件失败。


html模板

到此我们只实现了后端的内容,还需要前端页面才能正常使用,因为我们对前端页面不做要求,所以我们只需要简单的把内容显示出来即可,以下是前端代码。

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>文件共享</title>
    <style>
        html {
            font-family: sans-serif;
        }
        body {
            max-width: 80%;
            margin: 20px auto;
        }
        header {
            font-size: 50px;
            font-weight: 1000;
            text-align: center;
        }
        main {
            max-width: 100%;
        }
        p {
            font-size: 16px;
            font-weight: 800;
        }
        div {
            width: fit-content;
            display: inline-flex;
            align-content: flex-start;
            flex-wrap: wrap;
            flex-shrink: 2;
        }
        form {
            width: fit-content;
            margin-top: 25px;
            border: 2px solid royalblue;
        }
        ul {
            list-style-type: none;
        }
        a:hover {
            color: red;
        }
        input:hover {
            background-color: greenyellow;
        }
    </style>
</head>
<body>
    <header>文件共享系统</header>
    <main>
        <p>
            当前路径:{% if currentpath %} {{ currentpath }}&nbsp;<a href="../">(点这返回上一级)</a> {% else %} root {% endif %} 
        </p>
        <div>
            <ul id="filelist">
                {% for dir in dirlist %}
                    <li style="height:25px"><a href="{{ dir }}">{{ dir }}</a><span style="color:gray;font-size:10px">&nbsp;&nbsp;目录<span></li>
                {% endfor %}
                
                {% for file in filelist %}
                    <li style="height:25px"><a href="{{ file['name'] }}">{{ file['name'] }}</a><span style="color:gray">&nbsp;&nbsp;({{ file['size'] }})<span></li>
                {% endfor %}
            </ul>
        </div>
        <form action="#" id="uploadForm" method="post" enctype="multipart/form-data">
            <input type="file" id="fileInput" name="file" accept="*/*" onchange="isFileSelected()" />
            <input type="submit" id="fileupload" value="上传" disabled/>
        </form>
    </main>
    <script>
        // 判断文件是否选择
        function isFileSelected() {
            var fileInput = document.getElementById('fileInput');  // 获取文件选择控件的id
            var fileupload = document.getElementById('fileupload');  // 获取上传控件的id
            if (fileInput.value) {
                fileupload.removeAttribute("disabled");
            } else {
                fileupload.setAttribute("disabled", "disabled");
            }
        }

        // 提交表单,并以提示框的方式显示返回结果
        const form = document.getElementById('uploadForm');
        form.addEventListener('submit', function(event) {
            event.preventDefault();
            var formData = new FormData(form);
            fetch('/upload/', {
                method: 'POST',
                body: formData
            }).then(response => response.text())
            .then(data => {
                alert(data);
                window.location.reload();
            })
        })
    </script>
</body>
</html>

我们在读取目录内容部分用了render_template来渲染模板,使用了这个方法,我们就可以在html中使用一些特定的关键字来使用后端传来的变量了。

我使用了{% if currentpath %} {{ currentpath }}&nbsp;<a href="../">(点这返回上一级)</a> {% else %} root {% endif %} 来判断当前的显示路径,如果是根目录data就显示为root,如果在data下面的子目录中,则显示实际路径。还是用了两个for循环{% for dir in dirlist %}...{% endfor %}列出文件夹和文件。

然后使用了一个form表单实现选择文件和上传,并且使用JS脚本控制上传按钮的可用,如果选择文件的控件有文件,则上传按钮可用,若没有选中文件,上传按钮则不可用。

此外,还在JS脚本中实现了上传文件功能,并将结果返回到JS的alert警告框中。

到此整个文件分享系统就介绍完了,最后在flask程序中加上以下代码,让程序能在脚本中运行。

if __name__ == "__main__":
    app.run(host='0.0.0.0',debug=False)

然后使用python share.py即可运行程序。


效果

编写过程介绍完了,下面来看看实际效果
访问主页的效果
在这里插入图片描述
上传成功的提示框
在这里插入图片描述
目录和文件的显示效果
在这里插入图片描述
如果想直接要源码的话,可关注我的公众号回复关键词【flask文件分享系统】获取
在这里插入图片描述


原文地址:https://blog.csdn.net/jayhgq/article/details/140578660

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!