Python番外篇:Flask框架实现一个文件共享服务器

725 阅读3分钟

本人已参与【新人创作礼】活动,一起开启掘金创作之路。 本文首发于CSDN

hello,大家好,我是wangzirui32,今天来教大家如何使用Flask框架实现一个文件共享服务器。
开始学习吧!\

学习目录

前言

在工作中,我们时不时会遇到多个人同时向我们需求同一份文件,而手工一个一个发电子邮件,太累,所以诞生了这款文件共享服务器。这款服务器拥有上传文件和下载文件的功能,开启后,整个局域网内连接的设备,都能访问到这个文件共享服务器,并使用它的所有功能。

1. 项目架构

项目结构如下:
在这里插入图片描述
files文件夹下有三个测试文件,templates里准备了四个HTML模板。

2. app.py编写

代码奉上:

from flask import Flask
from flask import render_template, send_from_directory, request, redirect, url_for
import os
import time

# 全局变量 共享的文件夹路径 可以根据需求更改
DIRECTORY_PATH = r"C:\Users\wangzirui32\Desktop\Flask局域网文件共享\files"

# 创建项目
app = Flask(__name__)
app.config['SECURE_KEY'] = 'askydiqyddiudhiudiwuhdhdyjqoijd'

# 获取文件信息的函数
def get_files_data():
    files = []
    for i in os.listdir(DIRECTORY_PATH):
        if len(i.split(".")) == 1: # 判断此文件是否为一个文件夹
            continue
            
        # 拼接路径
        file_path = DIRECTORY_PATH+"/"+i
        name = i
        size = os.path.getsize(file_path) # 获取文件大小
        ctime = time.localtime(os.path.getctime(file_path)) # 格式化创建当时的时间戳

        # 列表信息
        files.append({
            "name": name,
            "size": size,
            "ctime": "{}年{}月{}日".format(ctime.tm_year, ctime.tm_mon, ctime.tm_mday),  # 拼接年月日信息
        })
    return files

@app.route("/")
def index():
    """共享文件主页"""
    return render_template("index.html", files=get_files_data())

@app.route("/download_file/<filename>")
def file_content(filename):
    """下载文件的URL"""
    if filename in os.listdir(DIRECTORY_PATH): # 如果需求下载文件存在
        # 发送文件 参数:文件夹路径,文件路径,文件名
        return send_from_directory(DIRECTORY_PATH, DIRECTORY_PATH+"/"+filename, filename)
    else:
        # 否则返回错误页面
        return render_template("download_error.html", filename=filename)

@app.route("/upload_file", methods=['GET', 'POST'])
def upload():
	"""上传文件的URL 支持GET/POST请求"""
    if request.method == "POST":
    	# 获取文件 拼接存储路径并保存
        upload_file = request.files.get("upload_file")
        upload_file.save(os.path.join(DIRECTORY_PATH, upload_file.filename))

		#  返回上传成功的模板
        return render_template("upload_ok.html", filename=upload_file.filename)

	# 上传的网页
    return render_template("upload.html")

if __name__ == '__main__':
	# 在局域网上开启端口
    app.run(host="0.0.0.0", port="8000")

服务器在本机上开了一个端口,局域网内的所有已经连接的设备都可以访问。

3. HTML模板编写

HTML的模板编写稍微复杂一点。

3.1 index.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>FLASK局域网文件共享</title>
    <!-- 标签的CSS样式设置 看不懂没关系 只要知道它布置了HTML页面的样式就行-->
    <style>
        body {
            padding: 20px;
        }
        .files-table {
            border-radius: 10px;
            width: 1000px;
            border: 3px solid blue;
            background-color: lightyellow;
        }
        .files-table td {
            width: 150px;
            height: 20px;
            text-align: center;
            font-size: 25px;
        }
        .td-name {
            color: coral;
        }
        .td-name a, a:link, a:visited {
            color: coral;
        }
        .td-size {
            color: dodgerblue;
        }
        .td-ctime {
            color: goldenrod;
        }
        h4 a {
            text-decoration: none;
            border: 3px solid cyan;
            border-radius: 5px;
        }
    </style>
</head>
<body>
    <h1>FLASK局域网文件共享</h1>
    <table class="files-table" border="1">
        <tr><!-- 表头 -->
            <td class="td-name">文件名</td>
            <td class="td-size">大小</td>
            <td class="td-ctime">创建日期</td>
        </tr>
        <!-- 将传上来的files进行遍历 输出HTML标签 -->
        {% for file in files %}
            <tr>
                <td class="td-name"><a href="/download_file/{{file.name}}">{{file.name}}</a></td>
                <td class="td-size">{{file.size}} B</td>
                <td class="td-ctime">{{file.ctime}}</td>
            </tr>
        {% endfor %}
    </table>
    <h4><a href="/upload_file">----->去上传文件</a></h4>
</body>
</html>

3.2 upload.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>
        body {
            padding: 10px;
        }
        h1 {
            color: orange;
        }
        form {
            border-radius: 10px;
            border: 5px solid red;
            width: 400px;
            height: 145px;
            background-color:lightskyblue;
        }
        form h3 {
            padding-left: 10px;
        }
        form input {
            color: coral;
        }
        form button {
            position: relative;
            width: 100px;
            height: 40px;
            color: deepskyblue;
            font-size: 25px;
            left: 10px;
        }
    </style>
</head>
<body>
    <h1>上传文件</h1>
    <!-- enctype="multipart/form-data" 设置表单的文件以二进制方式上传 就可以上传多种不同的文件 -->
    <form name="upload_form" action="#" method="post" enctype="multipart/form-data">
        <h3>请选择上传的文件:<input type="file" name="upload_file" /></h4>
        <button type="submit">提交</button>
    </form>
</body>
</html>

3.3 download_error.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>
</head>
<body>
    <h3>您所访问的"{{filename}}"文件并不存在!请点击<a href="/">链接</a>回到主页!</h3>
</body>
</html>

3.4 upload_ok.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>
</head>
<body>
    <h2>您所上传的"{{filename}}"已经存储到了服务器中,请前往<a href="/">主页</a>进行其他操作!</h2>
</body>
</html>

4. 效果展示

运行app.py中的代码,并访问主页(http://你的局域网IP地址:8000):
主页
点击"myFile.txt",可以看到,成功读取文件内容:
下载
将浏览器URL里的"myFile.txt"改为"myFile",测试下载错误页面:
下载错误
接下来,访问文件上传页面,选择文件,进行上传:
上传文件
点击“提交”,可以看到:
上传成功
files文件夹也变成了:
files
这个项目还可以拓展,如增加一个上传错误的页面,或者增加一个用户系统等等。


好了,今天的课程就到这里,我是wangzirui32,我们下次再见!