python3快速实现简单的多文件上传下载服务,妈妈再也不用担心我局域网的文件传输了

这段代码实现了一个简单的文件上传和下载服务器,使用 http.serversocketserver 模块构建了一个 HTTP 服务器,并支持文件的上传和下载。代码可以直接粘贴使用。无需改动文件会上传到该py文件的当前目录下的uploads目录下,可以指定别的目录(自行修改代码)

代码解释与注释

import http.server
import socketserver
import cgi
import os
import argparse

# 默认上传目录
UPLOAD_DIR = 'uploads'
os.makedirs(UPLOAD_DIR, exist_ok=True)  # 确保上传目录存在,如果不存在则创建

class CustomHTTPRequestHandler(http.server.SimpleHTTPRequestHandler):
    
    def do_GET(self):
        # 处理 GET 请求
        if self.path == '/':
            # 处理根路径请求,返回 HTML 页面
            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=UTF-8')  # 设置内容类型为 HTML,并指定 UTF-8 编码
            self.end_headers()

            # 获取上传目录中的文件列表
            file_list = os.listdir(UPLOAD_DIR)

            # 生成文件列表的 HTML
            file_list_html = '<ul>'
            for filename in file_list:
                file_list_html += f'<li>{filename}</li>'
            file_list_html += '</ul>'

            # 返回文件上传和下载表单,以及文件列表
            self.wfile.write(f'''
            <html>
            <meta charset="UTF-8">
            <title>文件 上传/下载</title>
            <body>
            <h1>上传文件</h1>
            <form id="uploadForm" enctype="multipart/form-data" method="POST">
                <input type="file" name="file" multiple οnchange="toggleUploadButton()">
                <button type="submit" id="uploadButton" disabled>Upload</button>
            </form>
            <h1>上传目录已有文件</h1>
            <div id="fileList">
                {file_list_html}
            </div>
            <h1>根据文件全称下载文件</h1>
            <form method="GET" action="/download">
                <input type="text" name="filename" placeholder="Enter filename">
                <input type="submit" value="Download">
            </form>
            <script>
            function toggleUploadButton() {{
                // 根据文件选择框中的文件数量来启用或禁用上传按钮
                var fileInput = document.querySelector('input[type="file"]');
                var uploadButton = document.getElementById('uploadButton');
                uploadButton.disabled = fileInput.files.length === 0;
            }}

            // 监听表单提交事件
            document.getElementById('uploadForm').onsubmit = function(event) {{
                event.preventDefault(); // 阻止表单默认提交行为

                // 创建 FormData 对象
                var formData = new FormData(this);
                var xhr = new XMLHttpRequest();
                xhr.open('POST', '/', true);

                xhr.onload = function() {{
                    if (xhr.status === 200) {{
                        alert('Files uploaded successfully');
                        document.querySelector('input[type="file"]').value = ''; // 清空文件选择框
                        toggleUploadButton(); // 重新禁用上传按钮
                        updateFileList(); // 更新文件列表
                    }} else {{
                        alert('Error uploading files');
                    }}
                }};
                
                xhr.send(formData);
            }};

            // 更新文件列表
            function updateFileList() {{
                var xhr = new XMLHttpRequest();
                xhr.open('GET', '/filelist', true);

                xhr.onload = function() {{
                    if (xhr.status === 200) {{
                        document.getElementById('fileList').innerHTML = xhr.responseText;
                    }} else {{
                        alert('Error fetching file list');
                    }}
                }};
                
                xhr.send();
            }}
            </script>
            </body>
            </html>
            '''.encode('utf-8'))  # 使用 UTF-8 编码返回 HTML 内容

        elif self.path.startswith('/download'):
            # 处理下载请求
            filename = self.path.split('filename=')[-1]
            filepath = os.path.join(UPLOAD_DIR, filename)
            if os.path.exists(filepath):
                self.send_response(200)
                self.send_header('Content-Disposition', f'attachment; filename="{filename}"')
                self.end_headers()
                with open(filepath, 'rb') as file:
                    self.wfile.write(file.read())  # 发送文件内容
            else:
                self.send_response(404)
                self.end_headers()
                self.wfile.write(b'File not found')  # 文件未找到

        elif self.path == '/filelist':
            # 处理文件列表请求
            file_list = os.listdir(UPLOAD_DIR)
            file_list_html = '<ul>'
            for filename in file_list:
                file_list_html += f'<li>{filename}</li>'
            file_list_html += '</ul>'

            self.send_response(200)
            self.send_header('Content-type', 'text/html; charset=UTF-8')  # 设置内容类型为 HTML,并指定 UTF-8 编码
            self.end_headers()
            self.wfile.write(file_list_html.encode('utf-8'))  # 返回文件列表的 HTML 内容

    def do_POST(self):
        # 处理 POST 请求
        if self.path == '/':
            # 使用 cgi.FieldStorage() 处理表单数据
            form = cgi.FieldStorage(fp=self.rfile, headers=self.headers, environ={'REQUEST_METHOD': 'POST'})
            
            if 'file' in form:
                # 处理上传的文件
                files = form['file']
                if not isinstance(files, list):
                    files = [files]
                
                for file_field in files:
                    if file_field.filename:
                        file_name = os.path.basename(file_field.filename)  # 获取原始文件名
                        file_data = file_field.file.read()  # 读取文件数据

                        # 保存文件
                        file_path = os.path.join(UPLOAD_DIR, file_name)
                        with open(file_path, 'wb') as f:
                            f.write(file_data)

                # 返回成功响应
                self.send_response(200)
                self.end_headers()
                self.wfile.write(b'Files uploaded successfully')
            else:
                self.send_response(400)
                self.end_headers()
                self.wfile.write(b'No files uploaded')  # 没有上传文件

def run_server(port):
    # 启动 HTTP 服务器
    Handler = CustomHTTPRequestHandler
    with socketserver.TCPServer(("", port), Handler) as httpd:
        print(f"Serving at port {port}")
        httpd.serve_forever()

if __name__ == '__main__':
    # 使用 argparse 来解析命令行参数
    parser = argparse.ArgumentParser(description="Simple file upload/download server")
    parser.add_argument('--port', type=int, default=8000, help='Port to serve on (default: 8000)')
    
    args = parser.parse_args()
    
    # 启动服务器
    run_server(args.port)

主要功能:

  1. 处理 GET 请求

    • 根路径 /:显示文件上传表单、当前文件列表和文件下载表单。
    • /download:根据文件名下载指定文件。
    • /filelist:返回当前上传目录中的文件列表。
  2. 处理 POST 请求

    • 根路径 /:处理文件上传,将文件保存到指定目录。
  3. JavaScript 代码

    • 处理文件选择变化,启用或禁用上传按钮。
    • 使用 AJAX 提交文件上传表单并更新文件列表。
  4. 服务器启动

    • 使用 argparse 解析命令行参数,允许通过 --port 参数指定端口,默认端口为 8000。

使用说明:

  1. 启动服务器

    • 运行 python <your_script_name>.py
    • 可以使用 --port 参数指定端口,例如 python <your_script_name>.py --port 8080
  2. 访问网页

    • 打开浏览器并访问 http://127.0.0.1:8000/(或指定的端口)。
  3. 上传文件

    • 选择文件并点击“Upload”按钮。
    • 上传成功后,文件会自动显示在文件列表中。
  4. 下载文件

    • 输入文件名并点击“Download”按钮来下载文件。
  • 5
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值