FTP局域网功能小网站V2_2

前言

为FTP局域网小网站增加密钥验证:从裸奔到安全可控

在之前的版本中,我们的FTP局域网小网站存在一个明显的安全隐患:任何连接到同一路由器的设备都可以直接访问所有文件。虽然这带来了极致的便利性(无需登录、无需配置),但也意味着:公共WiFi环境下,陌生人可能访问你的私人文件。

为了解决这个问题,我决定为工具增加API密钥验证机制,在保持便捷性的同时提升安全性。

具体大版本和这个保持一致: FTP局域网功能小网站V2

本文相当于2.1版本增加一个鉴权功能。

电脑端:

手机端:

输入的密钥在app.py中设置

python 复制代码
# 定义访问密钥
ACCESS_KEY = "211985"  # 可以根据实际需求修改

代码

代码结构如下:

download_page.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>下载文件 - FTP功能小网站</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4F46E5',
                    }
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .file-item-hover {
                @apply bg-blue-50;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-teal-50 min-h-screen font-sans text-gray-800">
    <div class="container mx-auto px-4 py-8 max-w-4xl relative">
        <!-- 登出按钮 -->
        <div class="absolute top-0 right-0 mt-2 mr-2">
            <a href="{{ url_for('logout') }}" class="inline-flex items-center text-gray-500 hover:text-primary transition-colors px-3 py-2 rounded-lg hover:bg-primary/5">
                <i class="fa fa-sign-out mr-1"></i>
                <span>登出</span>
            </a>
        </div>
        
        <!-- 页面标题 -->
        <header class="text-center mb-10 mt-6">
            <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-primary mb-2">
                <i class="fa fa-cloud-download mr-3"></i>文件下载
            </h1>
            <p class="text-gray-500">选择您需要下载的文件</p>
        </header>
        
        <!-- 文件列表卡片 -->
        <div class="bg-white rounded-xl shadow-md overflow-hidden mb-8">
            <!-- 列表头部 -->
            <div class="bg-gray-50 px-6 py-4 border-b border-gray-100">
                <h2 class="font-semibold text-gray-700">可供下载的文件</h2>
            </div>
            
            <!-- 文件列表 -->
            <div class="divide-y divide-gray-100">
                {% if fl and fl|length > 0 %}
                    {% for file in fl %}
                    <div class="px-6 py-4 flex items-center justify-between transition-all duration-200 hover:file-item-hover">
                        <!-- 文件名 -->
                        <div class="flex items-center">
                            <div class="w-10 h-10 rounded bg-gray-100 flex items-center justify-center mr-4 text-gray-500">
                                <i class="fa fa-file-o"></i>
                            </div>
                            <span class="font-medium text-gray-800 truncate max-w-md">{{ file }}</span>
                        </div>
                        
                        <!-- 下载按钮 -->
                        <a href="{{ url_for('download_file', filename=file) }}" 
                           class="inline-flex items-center bg-primary/10 text-primary px-4 py-2 rounded-lg transition-all duration-200 hover:bg-primary hover:text-white">
                            <i class="fa fa-download mr-2"></i>
                            <span>下载</span>
                        </a>
                    </div>
                    {% endfor %}
                {% else %}
                    <!-- 空状态 -->
                    <div class="px-6 py-16 text-center">
                        <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-gray-100 text-gray-400 mb-4">
                            <i class="fa fa-folder-open-o text-2xl"></i>
                        </div>
                        <p class="text-gray-500">暂无可供下载的文件</p>
                    </div>
                {% endif %}
            </div>
        </div>
        
        <!-- 返回按钮 -->
        <div class="text-center">
            <a href="{{ url_for('home') }}" class="inline-flex items-center text-primary hover:text-primary/80 transition-colors">
                <i class="fa fa-arrow-left mr-2"></i>返回首页
            </a>
        </div>
        
        <!-- 页脚 -->
        <footer class="mt-16 text-center text-gray-400 text-sm">
            <p>© 2025 FTP功能小网站 - 便捷快速的文件传输服务 - AndyDennis</p>
        </footer>
    </div>
    
    <!-- 简单的动画效果 -->
    <script>
        // 添加页面加载动画
        document.addEventListener('DOMContentLoaded', () => {
            const fileItems = document.querySelectorAll('.divide-y > div');
            fileItems.forEach((item, index) => {
                setTimeout(() => {
                    item.classList.add('animate-fade-in');
                }, 100 * index);
            });
        });
        
        // 添加动画样式
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .animate-fade-in {
                animation: fadeIn 0.3s ease-out forwards;
            }
        `;
        document.head.appendChild(style);
    </script>
</body>
</html>

home.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>FTP功能小网站</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4F46E5', // 主色调:靛蓝色,传达信任和专业感
                        secondary: '#8B5CF6', // 辅助色:紫色
                        neutral: '#F8FAFC', // 中性色:浅灰
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .btn-hover {
                @apply transform transition-all duration-300 hover:scale-105 hover:shadow-lg;
            }
            .card-effect {
                @apply bg-white rounded-xl shadow-md transition-all duration-300 hover:shadow-xl;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-neutral to-blue-50 min-h-screen flex flex-col items-center justify-center p-4 font-sans text-gray-800">
    <!-- 页面容器 -->
    <div class="max-w-md w-full mx-auto text-center relative">
        
        <!-- 标题区域 -->
        <div class="mb-12 animate-fade-in">
            <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary mb-4">
                <i class="fa fa-cloud-upload text-3xl"></i>
            </div>
            <h1 class="text-[clamp(2rem,5vw,3rem)] font-bold text-primary mb-2">FTP功能小网站</h1>
            <p class="text-gray-500">简单高效的文件上传与下载服务</p>
        </div>
        
        <!-- 操作按钮区域 -->
        <div class="grid gap-6">
            <!-- 上传按钮 -->
            <a href="{{ url_for('upload_file') }}" class="card-effect p-6 flex items-center justify-center space-x-3 btn-hover group">
                <div class="w-10 h-10 rounded-full bg-green-100 flex items-center justify-center text-green-600 group-hover:bg-green-600 group-hover:text-white transition-colors">
                    <i class="fa fa-upload"></i>
                </div>
                <span class="text-lg font-medium">上传文件</span>
            </a>
            
            <!-- 下载按钮 -->
            <a href="{{ url_for('download_page') }}" class="card-effect p-6 flex items-center justify-center space-x-3 btn-hover group">
                <div class="w-10 h-10 rounded-full bg-blue-100 flex items-center justify-center text-blue-600 group-hover:bg-blue-600 group-hover:text-white transition-colors">
                    <i class="fa fa-download"></i>
                </div>
                <span class="text-lg font-medium">下载文件</span>
            </a>
        </div>
        
        <!-- 页脚 -->
        <footer class="mt-16 text-gray-400 text-sm">
            <p>© 2025 FTP功能小网站 - 便捷快速的文件传输服务 - AndyDennis</p>
        </footer>
    </div>
    
    <!-- 简单的动画效果脚本 -->
    <script>
        // 添加页面加载动画类
        document.addEventListener('DOMContentLoaded', () => {
            const cards = document.querySelectorAll('.card-effect');
            cards.forEach((card, index) => {
                setTimeout(() => {
                    card.classList.add('animate-slide-up');
                }, 100 * index);
            });
        });
        
        // 定义简单的CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            @keyframes slideUp {
                from { opacity: 0; transform: translateY(20px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .animate-fade-in {
                animation: fadeIn 0.6s ease-out forwards;
            }
            .animate-slide-up {
                animation: slideUp 0.5s ease-out forwards;
            }
        `;
        document.head.appendChild(style);
    </script>
</body>
</html>

login.html (2.2新增)

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录 - FTP功能小网站</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色和字体 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4F46E5', // 主色调:靛蓝色,传达信任和专业感
                        secondary: '#8B5CF6', // 辅助色:紫色
                        neutral: '#F8FAFC', // 中性色:浅灰
                    },
                    fontFamily: {
                        sans: ['Inter', 'system-ui', 'sans-serif'],
                    },
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .content-auto {
                content-visibility: auto;
            }
            .btn-hover {
                @apply transform transition-all duration-300 hover:scale-105 hover:shadow-lg;
            }
            .card-effect {
                @apply bg-white rounded-xl shadow-md transition-all duration-300 hover:shadow-xl;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-neutral to-blue-50 min-h-screen flex flex-col items-center justify-center p-4 font-sans text-gray-800">
    <!-- 页面容器 -->
    <div class="max-w-md w-full mx-auto text-center">
        <!-- 标题区域 -->
        <div class="mb-12 animate-fade-in">
            <div class="inline-flex items-center justify-center w-16 h-16 rounded-full bg-primary/10 text-primary mb-4">
                <i class="fa fa-lock text-3xl"></i>
            </div>
            <h1 class="text-[clamp(2rem,5vw,3rem)] font-bold text-primary mb-2">请输入密钥</h1>
            <p class="text-gray-500">需要验证身份才能访问FTP功能</p>
        </div>
        
        <!-- 登录表单 -->
        <div class="card-effect p-8 animate-slide-up">
            {% if error %}
            <div class="mb-4 p-3 bg-red-100 text-red-700 rounded-lg">
                {{ error }}
            </div>
            {% endif %}
            <form method="POST" action="{{ url_for('login') }}">
                <div class="mb-6">
                    <label for="key" class="block text-left text-gray-700 mb-2">密钥</label>
                    <div class="relative">
                        <span class="absolute inset-y-0 left-0 flex items-center pl-3 text-gray-400">
                            <i class="fa fa-key"></i>
                        </span>
                        <input type="password" id="key" name="key" 
                               class="w-full pl-10 pr-4 py-3 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-primary/50 focus:border-primary transition-colors"
                               placeholder="请输入访问密钥" required>
                    </div>
                </div>
                <button type="submit" 
                        class="w-full bg-primary text-white py-3 px-6 rounded-lg font-medium btn-hover flex items-center justify-center space-x-2">
                    <i class="fa fa-sign-in"></i>
                    <span>验证密钥</span>
                </button>
            </form>
        </div>
        
        <!-- 页脚 -->
        <footer class="mt-16 text-gray-400 text-sm">
            <p>© 2025 FTP功能小网站 - 便捷快速的文件传输服务 - AndyDennis</p>
        </footer>
    </div>
    
    <!-- 简单的动画效果脚本 -->
    <script>
        // 添加页面加载动画类
        document.addEventListener('DOMContentLoaded', () => {
            const cards = document.querySelectorAll('.card-effect');
            cards.forEach((card, index) => {
                setTimeout(() => {
                    card.classList.add('animate-slide-up');
                }, 100 * index);
            });
        });
        
        // 定义简单的CSS动画
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            @keyframes slideUp {
                from { opacity: 0; transform: translateY(20px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .animate-fade-in {
                animation: fadeIn 0.6s ease-out forwards;
            }
            .animate-slide-up {
                animation: slideUp 0.5s ease-out forwards;
            }
        `;
        document.head.appendChild(style);
    </script>
</body>
</html>

upload_success.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>上传成功 - FTP功能小网站</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4F46E5',
                        success: '#10B981', // 成功状态颜色
                    }
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .btn-action {
                @apply px-6 py-3 rounded-lg font-medium transition-all duration-300 hover:shadow-lg transform hover:-translate-y-0.5;
            }
            .btn-primary {
                @apply bg-primary text-white hover:bg-primary/90;
            }
            .btn-secondary {
                @apply bg-gray-100 text-gray-700 hover:bg-gray-200;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-teal-50 min-h-screen font-sans flex items-center justify-center p-4">
    <div class="max-w-md w-full text-center relative">
        <!-- 登出按钮 -->
        <div class="absolute top-0 right-0 mt-2 mr-2">
            <a href="{{ url_for('logout') }}" class="inline-flex items-center text-gray-500 hover:text-primary transition-colors px-3 py-2 rounded-lg hover:bg-primary/5">
                <i class="fa fa-sign-out mr-1"></i>
                <span>登出</span>
            </a>
        </div>
        
        <!-- 成功状态卡片 -->
        <div class="bg-white rounded-2xl shadow-lg p-8 md:p-10 transform transition-all duration-500 animate-float">
            <!-- 成功图标 -->
            <div class="w-20 h-20 mx-auto bg-success/10 rounded-full flex items-center justify-center mb-6 animate-pulse-slow">
                <i class="fa fa-check text-4xl text-success"></i>
            </div>
            
            <!-- 成功信息 -->
            <h1 class="text-[clamp(1.5rem,3vw,2rem)] font-bold text-gray-800 mb-3">上传成功!</h1>
            <p class="text-gray-600 mb-8">
                文件 <span class="font-medium text-primary">{{ filename }}</span> 已成功上传
            </p>
            
            <!-- 文件信息 -->
            <div class="bg-gray-50 rounded-lg p-4 mb-8 text-left">
                <div class="flex items-center text-sm text-gray-500">
                    <i class="fa fa-file-text-o w-5 text-gray-400"></i>
                    <span class="ml-2 truncate">{{ filename }}</span>
                </div>
            </div>
            
            <!-- 操作按钮 -->
            <div class="flex flex-col sm:flex-row gap-4 justify-center">
                <a href="{{ url_for('upload_file') }}" class="btn-action btn-primary flex items-center justify-center">
                    <i class="fa fa-upload mr-2"></i>上传另一个文件
                </a>
                <a href="{{ url_for('home') }}" class="btn-action btn-secondary flex items-center justify-center">
                    <i class="fa fa-home mr-2"></i>返回首页
                </a>
            </div>
        </div>
        
        <!-- 页脚 -->
        <footer class="mt-10 text-gray-400 text-sm">
            <p>© 2025 FTP功能小网站 - 便捷快速的文件传输服务 - AndyDennis</p>
        </footer>
    </div>
    
    <!-- 动画样式 -->
    <style>
        @keyframes float {
            0%, 100% { transform: translateY(0); }
            50% { transform: translateY(-10px); }
        }
        @keyframes pulseSlow {
            0%, 100% { transform: scale(1); }
            50% { transform: scale(1.05); }
        }
        .animate-float {
            animation: float 3s ease-in-out infinite;
        }
        .animate-pulse-slow {
            animation: pulseSlow 2s ease-in-out infinite;
        }
    </style>
</body>
</html>

upload.html

html 复制代码
<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>上传文件 - FTP功能小网站</title>
    <!-- 引入Tailwind CSS -->
    <script src="https://cdn.tailwindcss.com"></script>
    <!-- 引入Font Awesome -->
    <link href="https://cdn.jsdelivr.net/npm/font-awesome@4.7.0/css/font-awesome.min.css" rel="stylesheet">
    
    <!-- 配置Tailwind自定义颜色 -->
    <script>
        tailwind.config = {
            theme: {
                extend: {
                    colors: {
                        primary: '#4F46E5',
                        secondary: '#8B5CF6',
                        accent: '#10B981', // 上传相关的强调色(绿色)
                    }
                }
            }
        }
    </script>
    
    <style type="text/tailwindcss">
        @layer utilities {
            .file-upload-hover {
                @apply border-accent bg-accent/5;
            }
            .btn-primary {
                @apply bg-primary text-white px-6 py-3 rounded-lg font-medium transition-all duration-300 hover:bg-primary/90 hover:shadow-lg transform hover:-translate-y-0.5;
            }
            .card {
                @apply bg-white rounded-xl shadow-md p-6 md:p-8 transition-all duration-300 hover:shadow-xl;
            }
        }
    </style>
</head>
<body class="bg-gradient-to-br from-blue-50 to-teal-50 min-h-screen font-sans">
    <div class="container mx-auto px-4 py-8 max-w-3xl relative">
        <!-- 登出按钮 -->
        <div class="absolute top-0 right-0 mt-2 mr-2">
            <a href="{{ url_for('logout') }}" class="inline-flex items-center text-gray-500 hover:text-primary transition-colors px-3 py-2 rounded-lg hover:bg-primary/5">
                <i class="fa fa-sign-out mr-1"></i>
                <span>登出</span>
            </a>
        </div>
        
        <!-- 页面标题 -->
        <header class="text-center mb-10 mt-6">
            <h1 class="text-[clamp(1.8rem,4vw,2.5rem)] font-bold text-primary mb-2">
                <i class="fa fa-cloud-upload mr-3"></i>上传文件
            </h1>
            <p class="text-gray-500">选择并上传您需要存储的文件</p>
        </header>
        
        <!-- 上传卡片 -->
        <div class="card mb-8">
            <!-- 拖放区域 -->
            <div id="drop-area" class="border-2 border-dashed border-gray-300 rounded-lg p-8 text-center mb-6 transition-all duration-300">
                <i class="fa fa-file-o text-5xl text-gray-400 mb-4"></i>
                <p class="text-gray-600 mb-4">拖放文件到此处,或</p>
                
                <!-- 文件选择表单 -->
                <form action="{{ url_for('upload_success')}}" method="POST" enctype="multipart/form-data" id="upload-form">
                    <label for="file-upload" class="btn-primary inline-flex items-center">
                        <i class="fa fa-folder-open mr-2"></i>选择文件
                        <input id="file-upload" type="file" name="file" class="hidden" accept="*/*"/>
                    </label>
                    
                    <div id="file-info" class="mt-4 hidden">
                        <p class="text-gray-700"><span id="file-name"></span></p>
                        <p class="text-sm text-gray-500 mt-1" id="file-size"></p>
                    </div>
                    
                    <div class="mt-6">
                        <button type="submit" class="btn-primary">
                            <i class="fa fa-upload mr-2"></i>开始上传
                        </button>
                    </div>
                </form>
            </div>
            
            <!-- 上传说明 -->
            <div class="text-sm text-gray-500 bg-gray-50 p-4 rounded-lg">
                <p><i class="fa fa-info-circle text-primary mr-2"></i>上传说明:</p>
                <ul class="list-disc list-inside mt-2 space-y-1">
                    <li>请确保文件符合上传规范</li>
                    <li>支持多种文件格式上传</li>
                    <li>上传完成后将自动跳转至成功页面</li>
                </ul>
            </div>
        </div>
        
        <!-- 返回按钮 -->
        <div class="text-center">
            <a href="{{ url_for('home') }}" class="inline-flex items-center text-primary hover:text-primary/80 transition-colors">
                <i class="fa fa-arrow-left mr-2"></i>返回首页
            </a>
        </div>
        
        <!-- 页脚 -->
        <footer class="mt-16 text-center text-gray-400 text-sm">
            <p>© 2025 FTP功能小网站 - 便捷快速的文件传输服务 - AndyDennis</p>
        </footer>
    </div>
    
    <!-- 交互脚本 -->
    <script>
        // 获取DOM元素
        const dropArea = document.getElementById('drop-area');
        const fileInput = document.getElementById('file-upload');
        const fileInfo = document.getElementById('file-info');
        const fileName = document.getElementById('file-name');
        const fileSize = document.getElementById('file-size');
        const uploadForm = document.getElementById('upload-form');
        
        // 处理文件选择
        fileInput.addEventListener('change', (e) => {
            if (e.target.files.length > 0) {
                showFileInfo(e.target.files[0]);
            }
        });
        
        // 拖放功能
        ['dragenter', 'dragover', 'dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, preventDefaults, false);
        });
        
        function preventDefaults(e) {
            e.preventDefault();
            e.stopPropagation();
        }
        
        ['dragenter', 'dragover'].forEach(eventName => {
            dropArea.addEventListener(eventName, highlight, false);
        });
        
        ['dragleave', 'drop'].forEach(eventName => {
            dropArea.addEventListener(eventName, unhighlight, false);
        });
        
        function highlight() {
            dropArea.classList.add('file-upload-hover');
        }
        
        function unhighlight() {
            dropArea.classList.remove('file-upload-hover');
        }
        
        dropArea.addEventListener('drop', handleDrop, false);
        
        function handleDrop(e) {
            const dt = e.dataTransfer;
            const file = dt.files[0];
            
            if (file) {
                // 将拖放的文件设置到文件输入中
                fileInput.files = dt.files;
                showFileInfo(file);
            }
        }
        
        // 显示文件信息
        function showFileInfo(file) {
            fileName.textContent = `文件名: ${file.name}`;
            fileSize.textContent = `文件大小: ${formatFileSize(file.size)}`;
            fileInfo.classList.remove('hidden');
            
            // 添加显示动画
            fileInfo.classList.add('animate-fade-in');
        }
        
        // 格式化文件大小
        function formatFileSize(bytes, decimals = 2) {
            if (bytes === 0) return '0 Bytes';
            
            const k = 1024;
            const dm = decimals < 0 ? 0 : decimals;
            const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];
            
            const i = Math.floor(Math.log(bytes) / Math.log(k));
            
            return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + ' ' + sizes[i];
        }
        
        // 添加动画样式
        const style = document.createElement('style');
        style.textContent = `
            @keyframes fadeIn {
                from { opacity: 0; transform: translateY(10px); }
                to { opacity: 1; transform: translateY(0); }
            }
            .animate-fade-in {
                animation: fadeIn 0.3s ease-out forwards;
            }
        `;
        document.head.appendChild(style);
    </script>
</body>
</html>

app.py

python 复制代码
from flask import Flask, render_template, request, send_from_directory, abort, redirect, url_for, session
import os
import secrets
import time
import functools

app = Flask(__name__)
app.secret_key = secrets.token_hex(16)  # 用于加密session

# 定义访问密钥
ACCESS_KEY = "211985"  # 可以根据实际需求修改

# token有效期(秒)
TOKEN_EXPIRY = 3600  # 1小时


def getfile():
    print(os.getcwd())
    path1 = os.getcwd() + '/upload_files'
    path2 = os.getcwd()
    # 跳转目录 跳转到下载文件的目录,获得下载文件目录里面的list之后,然后再跳转出来.
   #这个跳转的步骤是为了获取到upload_files目录下的文件的名字,然后把它放进f_list中
    os.chdir(path1)
    f_list = os.listdir()
    os.chdir(path2)
    print(os.getcwd())
    return f_list


def is_Have_file(filename):
    print(os.getcwd())
    path1 = os.getcwd() + '/upload_files'
    path2 = os.getcwd()
    os.chdir(path1)
    flag = os.path.isfile(filename)
    os.chdir(path2)
    print(os.getcwd())
    return flag


# 登录装饰器,用于检查用户是否已登录
def login_required(f):
    @functools.wraps(f)
    def decorated_function(*args, **kwargs):
        # 检查session中是否有token和token过期时间
        if 'token' not in session or 'token_expiry' not in session:
            return redirect(url_for('login'))
        
        # 检查token是否过期
        if time.time() > session['token_expiry']:
            # token过期,清除session并跳转到登录页
            session.pop('token', None)
            session.pop('token_expiry', None)
            return redirect(url_for('login'))
        
        return f(*args, **kwargs)
    return decorated_function


# 登录路由
@app.route('/login', methods=['GET', 'POST'])
def login():
    if request.method == 'POST':
        # 获取用户输入的密钥
        key = request.form.get('key')
        
        # 验证密钥
        if key == ACCESS_KEY:
            # 生成token并保存到session
            session['token'] = secrets.token_hex(32)
            session['token_expiry'] = time.time() + TOKEN_EXPIRY
            
            # 重定向到首页
            return redirect(url_for('home'))
        else:
            # 密钥错误,显示错误信息
            return render_template('login.html', error='密钥错误,请重新输入')
    
    # GET请求,显示登录页
    return render_template('login.html')


# 登出路由
@app.route('/logout')
def logout():
    # 清除session中的token信息
    session.pop('token', None)
    session.pop('token_expiry', None)
    return redirect(url_for('login'))


@app.route('/')
@login_required
def home():
    return render_template('home.html')


@app.route('/upload')
@login_required
def upload_file():
    return render_template('upload.html')


@app.route('/uploader', methods=['GET', 'POST'])
@login_required
def upload_success():
    if request.method == 'POST':
        f = request.files['file']
        f.save('upload_files/' + f.filename)
        return render_template('upload_success.html', filename=f.filename)


# 显示下载文件的界面
@app.route('/down', methods=['GET'])
@login_required
def download_page():
    f_list = getfile()
    return render_template('download_page.html', fl=f_list)


# 下载要下载的文件,要下载的文件是通过get方法来传递的
@app.route('/download_file', methods=['GET'])
@login_required
def download_file():
    if request.method == 'GET':
        download_filename = request.args.get('filename')
        f_list = getfile()
        print()
        if is_Have_file(download_filename):
            return send_from_directory('upload_files', download_filename, as_attachment=True)
        else:
            abort(404)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000)
相关推荐
我材不敲代码2 小时前
在Linux系统上安装MySQL
linux·运维·服务器
小Tomkk2 小时前
分享 贪吃蛇小游戏 - 毕业设计完整资源包
课程设计·html5·毕设
珠海西格2 小时前
远动通信装置为何是电网安全运行的“神经中枢”?
大数据·服务器·网络·数据库·分布式·安全·区块链
小宇的天下3 小时前
Calibre 3Dstack --每日一个命令day18【floating_trace】(3-18)
服务器·前端·数据库
历程里程碑3 小时前
Linux15 进程二
linux·运维·服务器·开发语言·数据结构·c++·笔记
H Journey3 小时前
Linux su 命令核心用法总结
java·linux·服务器·su
岚天start3 小时前
Python HTTP服务器添加简单用户名密码认证的三种方案
服务器·python·http
H Journey3 小时前
Linux sudo 命令完全指南
linux·运维·服务器·sudo
开开心心_Every3 小时前
家常菜谱软件推荐:分类齐全无广告步骤详细
linux·运维·服务器·华为od·edge·pdf·华为云