
使用Python内置的http.server和cgi模块实现,适合快速部署内网文件共享服务。
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
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):
<!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中实现)
# 文件类型白名单
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 "文件类型不允许", 4002)大文件分块上传(使用Flask)
@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)添加基础认证(使用装饰器)
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():
...(1)开发环境:直接运行Flask应用(app.run())
(2)生产环境:
server {
listen 80;
client_max_body_size 100M; # 允许100MB大文件
location / {
proxy_pass http://localhost:8000;
}
}(3)安全配置:
标准库http.server方案适合快速临时、内网快速共享,Flask方案更适合长期稳定运行的服务,适合生产环境/复杂需求。可根据需求灵活选择。
“无他,惟手熟尔”!有需要的用起来。
如果你觉得这篇文章有用,欢迎点赞、转发、收藏、留言、推荐❤!
本文分享自 Nicholas与Pypi 微信公众号,前往查看
如有侵权,请联系 cloudcommunity@tencent.com 删除。
本文参与 腾讯云自媒体同步曝光计划 ,欢迎热爱写作的你一起参与!