首页
学习
活动
专区
圈层
工具
发布
社区首页 >专栏 >Python 快速开发Web文件服务器

Python 快速开发Web文件服务器

作者头像
用户11081884
发布2026-07-20 16:57:50
发布2026-07-20 16:57:50
340
举报

一、基于标准库的实现(python自带零依赖)

使用Python内置的http.servercgi模块实现,适合快速部署内网文件共享服务。

代码语言:javascript
复制
import http.server
import cgi
import os
import sys
from urllib.parse import urlparse, unquote

class FileHandler(http.server.BaseHTTPRequestHandler):
       UPLOAD_DIR = 'uploads'  # 上传目录配置

      def send_html_header(self):
        """发送 HTML 响应头"""
            self.send_response(200)  # 设置响应状态码为 200(OK)
            self.send_header('Content-type', 'text/html; charset=utf-8')  # 设置响应内容类型为 HTML
            self.end_headers()  # 结束响应头

    def do_POST(self):
        # 解析表单数据(含文件)
          form = cgi.FieldStorage(
            fp=self.rfile,
            headers=self.headers,
            environ={'REQUEST_METHOD': 'POST'}
        )

        # 获取上传文件并保存
        file_item = form['file']
        if file_item.filename:
            file_path = os.path.join(self.UPLOAD_DIR, os.path.basename(file_item.filename))
            with open(file_path, 'wb') as f:
                f.write(file_item.file.read())
            self.send_redirect('/')  # 上传后返回首页

    def do_GET(self):
        # 文件下载处理
        if self.path.startswith('/download/'):
            file_path = os.path.join(os.getcwd(), unquote(self.path[9:]))
            if os.path.isfile(file_path):
                self.send_header('Content-Disposition', f'attachment; filename="{os.path.basename(file_path)}"')
                with open(file_path, 'rb') as f:
                    self.wfile.write(f.read())
        # 显示文件列表
        else:
            self.send_html_header()
            self.wfile.write(self.generate_file_list().encode('utf-8'))

    def generate_file_list(self):
        """生成带上传表单的文件列表HTML"""
        files = os.listdir(self.UPLOAD_DIR)
        html = f"""
        <h2>文件列表</h2>
        <form method="post" enctype="multipart/form-data">
            <input type="file" name="file">
            <input type="submit" value="上传">
        </form>
        <ul>{"".join(f'<li><a href="/download/{f}">{f}</a></li>' for f in files)}</ul>
        """
        return html


if __name__ == '__main__':
    os.makedirs(FileHandler.UPLOAD_DIR, exist_ok=True)
    port = 8000 if len(sys.argv) < 2 else int(sys.argv)
    server = http.server.HTTPServer(('', port), FileHandler)
    print(f"文件服务器已启动: http://192.168.224.141:{port}")
    server.serve_forever()

使用说明:

1、启动服务:python server.py

2、上传文件:访问 http://localhost:8000 使用表单上传

3、下载文件:点击文件列表中的链接自动下载

4、定义端口:python server.py 8080

二、基于Flask的高效实现(推荐生产环境使用)

代码语言:javascript
复制
from flask import Flask, render_template, request, redirect, url_for, send_from_directory, abort
import os
from werkzeug.utils import secure_filename

app = Flask(__name__)
app.config['UPLOAD_FOLDER'] = 'uploads'
app.config['ALLOWED_EXTENSIONS'] = {'txt', 'pdf', 'png', 'jpg', 'jpeg', 'gif', 'zip'}

# 确保上传目录存在
os.makedirs(app.config['UPLOAD_FOLDER'], exist_ok=True)

def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

@app.route('/')
def index():
    # 获取上传目录中的文件列表
    files = []
    for filename in os.listdir(app.config['UPLOAD_FOLDER']):
        path = os.path.join(app.config['UPLOAD_FOLDER'], filename)
        if os.path.isfile(path):
            files.append({
                'name': filename,
                'size': os.path.getsize(path),
                'modified': os.path.getmtime(path)
            })
    return render_template('index.html', files=files)

@app.route('/upload', methods=['POST'])
def upload_file():
    if 'file' not in request.files:
        return redirect(request.url)

    file = request.files['file']
    if file.filename == '':
        return redirect(request.url)

    if file and allowed_file(file.filename):
        filename = secure_filename(file.filename)
        file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        return redirect(url_for('index'))

    return '文件类型不允许', 400


@app.route('/download/<filename>')
def download_file(filename):
    try:
        return send_from_directory(
            app.config['UPLOAD_FOLDER'],
            filename,
            as_attachment=True
        )
    except FileNotFoundError:
        abort(404)


if __name__ == '__main__':
    app.run(host='0.0.0.0', port=5000, debug=True)

配套模板文件(templates/index.html):

代码语言:javascript
复制
<!DOCTYPE html>
<html>
<head>
    <title>文件服务器</title>
    <style>
        body { font-family: Arial, sans-serif; margin: 20px; }
        table { width: 100%; border-collapse: collapse; }
        th, td { padding: 8px; text-align: left; border-bottom: 1px solid #ddd; }
        th { background-color: #f2f2f2; }
        .upload-form { margin: 20px 0; }
    </style>
</head>
<body>
    <h1>文件服务器</h1>
    
    <div class="upload-form">
        <h2>上传文件</h2>
        <form method="post" enctype="multipart/form-data" action="/upload">
            <input type="file" name="file">
            <button type="submit">上传</button>
        </form>
    </div>


    <h2>文件列表</h2>
    <table>
        <tr>
            <th>文件名</th>
            <th>大小 (字节)</th>
            <th>修改时间</th>
            <th>操作</th>
        </tr>
        {% for file in files %}
        <tr>
            <td>{{ file.name }}</td>
            <td>{{ file.size }}</td>
            <td>{{ file.modified|datetime }}</td>
            <td><a href="/download/{{ file.name }}">下载</a></td>
        </tr>
        {% endfor %}
    </table>
</body>
</html>

使用说明:

1、安装库:pip install flask werkzeug

2、运行服务:python file_server.py

3、访问地址:http://localhost:5000

4、扩展:

1)安全增强(在Flask中实现)

代码语言:javascript
复制
# 文件类型白名单
ALLOWED_EXTENSIONS = {'txt', 'pdf', 'png'}
def allowed_file(filename):
    return '.' in filename and \
           filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS

# 在上传路由中添加检查
if file and allowed_file(file.filename):
    file.save(...)
else:
    return "文件类型不允许", 400

2)大文件分块上传(使用Flask

代码语言:javascript
复制
@app.route('/chunk_upload', methods=['POST'])
def chunk_upload():
    chunk = request.files['chunk']
    chunk_number = request.form['chunkNumber']
    filename = request.form['filename']
    
    # 创建临时目录存储分块
    temp_dir = os.path.join(UPLOAD_FOLDER, 'temp', filename)
    os.makedirs(temp_dir, exist_ok=True)
    
    # 保存分块
    chunk.save(os.path.join(temp_dir, chunk_number))
    
    # 合并检测(当收到最后一块时)
    if int(chunk_number) == int(request.form['totalChunks']) - 1:
        merge_chunks(filename)
    
    return 'OK'

3)添加基础认证(使用装饰器)

代码语言:javascript
复制
from functools import wraps

def auth_required(f):
    @wraps(f)
    def decorated(*args, **kwargs):
        auth = request.authorization
        if auth and auth.username == 'admin' and auth.password == 'secret':
            return f(*args, **kwargs)
        return ('Unauthorized', 401, 
                {'WWW-Authenticate': 'Basic realm="Login Required"'})
    return decorated

# 在路由上添加装饰器
@app.route('/')
@auth_required
def index():
    ...

4)部署建议

(1)开发环境:直接运行Flask应用(app.run())

(2)生产环境

  • 使用Gunicorn部署:gunicorn -w 4 app:app
  • 配置Nginx反向代理(增加文件上传大小限制):
代码语言:javascript
复制
server {
    listen 80;
    client_max_body_size 100M;  # 允许100MB大文件
    location / {
        proxy_pass http://localhost:8000; 
    }
}

(3)安全配置

  • 禁用目录遍历:在文件列表生成时过滤敏感文件。
  • 设置文件大小上限:app.config[’MAX_CONTENT_LENGTH’] = 100 * 1024 * 1024。
  • 定期清理上传目录。

标准库http.server方案适合快速临时、内网快速共享,Flask方案更适合长期稳定运行的服务,适合生产环境/复杂需求。可根据需求灵活选择。

“无他,惟手熟尔”!有需要的用起来。

如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2025-07-15,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 Nicholas与Pypi 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、基于标准库的实现(python自带零依赖)
  • 二、基于Flask的高效实现(推荐生产环境使用)
  • 4)部署建议
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档