|
|
from flask import Flask, request, jsonify
|
|
|
import os
|
|
|
|
|
|
# 默认配置
|
|
|
DEFAULT_UPLOAD_FOLDER = "/mnt/sese/"
|
|
|
|
|
|
ALLOWED_EXTENSIONS = {
|
|
|
'png', 'jpg', 'jpeg', 'gif', 'bmp', 'tiff', 'webp', # 图片类型
|
|
|
'mp4', 'mov', 'wmv', 'avi', 'm4v', 'mpg', 'mpeg', 'flv', 'mkv', '3gp', 'webm' # 视频类型
|
|
|
}
|
|
|
MAX_FILE_SIZE = 88 * 1024 * 1024 # 88MB
|
|
|
|
|
|
app = Flask(__name__)
|
|
|
app.config['UPLOAD_FOLDER'] = DEFAULT_UPLOAD_FOLDER
|
|
|
app.config['MAX_CONTENT_LENGTH'] = MAX_FILE_SIZE
|
|
|
|
|
|
|
|
|
def allowed_file(filename):
|
|
|
return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS
|
|
|
|
|
|
|
|
|
def list_files(directory):
|
|
|
"""列出指定目录下的所有文件并按时间排序"""
|
|
|
if not os.path.exists(directory):
|
|
|
return []
|
|
|
files = []
|
|
|
for root, _, filenames in os.walk(directory):
|
|
|
for filename in filenames:
|
|
|
files.append(os.path.relpath(os.path.join(root, filename), directory))
|
|
|
files.sort(key=lambda x: os.path.getmtime(os.path.join(directory, x)), reverse=True) # 按时间降序排序
|
|
|
return files
|
|
|
|
|
|
|
|
|
@app.route('/upload', methods=['GET', 'POST'])
|
|
|
def upload_file():
|
|
|
if request.method == 'POST':
|
|
|
# 检查是否上传了文件
|
|
|
if 'file' not in request.files:
|
|
|
return jsonify({'status': 'error', 'message': 'No file part'}), 400
|
|
|
|
|
|
file = request.files['file']
|
|
|
if file.filename == '':
|
|
|
return jsonify({'status': 'error', 'message': 'No selected file'}), 400
|
|
|
|
|
|
# 获取自定义路径并检查合法性
|
|
|
custom_path = request.form.get('customPath', DEFAULT_UPLOAD_FOLDER).strip()
|
|
|
if custom_path:
|
|
|
# 验证路径合法性
|
|
|
if not os.path.isabs(custom_path): # 必须是绝对路径
|
|
|
return jsonify({'status': 'error', 'message': 'Path must be an absolute path'}), 400
|
|
|
if ".." in custom_path: # 禁止路径包含 ".." 防止目录跳跃
|
|
|
return jsonify({'status': 'error', 'message': 'Path not allowed'}), 400
|
|
|
else:
|
|
|
custom_path = DEFAULT_UPLOAD_FOLDER # 默认路径
|
|
|
|
|
|
# 创建完整保存路径
|
|
|
save_dir = os.path.abspath(custom_path)
|
|
|
if not os.path.exists(save_dir):
|
|
|
os.makedirs(save_dir)
|
|
|
|
|
|
# 检查文件类型并保存
|
|
|
if file and allowed_file(file.filename):
|
|
|
filepath = os.path.join(save_dir, file.filename)
|
|
|
file.save(filepath)
|
|
|
uploaded_files = list_files(save_dir) # 列举上传路径中的文件
|
|
|
return jsonify({'status': 'success', 'message': f'File uploaded to {save_dir}/{file.filename}',
|
|
|
'files': uploaded_files}), 200
|
|
|
|
|
|
return jsonify({'status': 'error', 'message': 'File type not allowed'}), 400
|
|
|
|
|
|
# GET 请求返回 HTML 页面
|
|
|
files = list_files(DEFAULT_UPLOAD_FOLDER)
|
|
|
# 显示最新10个文件,超出部分隐藏
|
|
|
files_to_show = files[:10]
|
|
|
files_hidden = files[10:]
|
|
|
|
|
|
files_list_html = ''.join(
|
|
|
f'<li>{file}</li>'
|
|
|
for file in files_to_show
|
|
|
)
|
|
|
hidden_files_html = ''.join(
|
|
|
f'<li class="hidden-file">{file}</li>'
|
|
|
for file in files_hidden
|
|
|
)
|
|
|
|
|
|
files_all_json = jsonify(files=files) # 传回所有文件列表,后续可以通过AJAX加载所有文件
|
|
|
|
|
|
html_template = f"""
|
|
|
<!DOCTYPE html>
|
|
|
<html lang="en">
|
|
|
<head>
|
|
|
<meta charset="UTF-8">
|
|
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
|
<title>File Upload</title>
|
|
|
<style>
|
|
|
body {{
|
|
|
font-family: Arial, sans-serif;
|
|
|
background-color: #f4f7fc;
|
|
|
padding: 20px;
|
|
|
}}
|
|
|
h1 {{
|
|
|
color: #4b4f56;
|
|
|
font-size: 2rem;
|
|
|
}}
|
|
|
ul {{
|
|
|
list-style-type: none;
|
|
|
padding-left: 0;
|
|
|
}}
|
|
|
li {{
|
|
|
margin: 5px 0;
|
|
|
padding: 10px;
|
|
|
background-color: #fff;
|
|
|
border: 1px solid #ccc;
|
|
|
border-radius: 5px;
|
|
|
}}
|
|
|
.hidden-file {{
|
|
|
display: none;
|
|
|
}}
|
|
|
button {{
|
|
|
padding: 10px 20px;
|
|
|
background-color: #28a745;
|
|
|
color: white;
|
|
|
border: none;
|
|
|
border-radius: 5px;
|
|
|
cursor: pointer;
|
|
|
font-size: 16px;
|
|
|
}}
|
|
|
button:hover {{
|
|
|
background-color: #218838;
|
|
|
}}
|
|
|
</style>
|
|
|
<script>
|
|
|
function uploadFile(event) {{
|
|
|
event.preventDefault();
|
|
|
const formData = new FormData(document.getElementById('uploadForm'));
|
|
|
const uploadButton = document.getElementById('uploadButton');
|
|
|
const progressIndicator = document.getElementById('progressIndicator');
|
|
|
const messageBox = document.getElementById('messageBox');
|
|
|
|
|
|
// 禁用按钮,显示上传中提示
|
|
|
uploadButton.disabled = true;
|
|
|
progressIndicator.style.display = 'inline-block';
|
|
|
|
|
|
fetch('/upload', {{
|
|
|
method: 'POST',
|
|
|
body: formData
|
|
|
}})
|
|
|
.then(response => response.json())
|
|
|
.then(data => {{
|
|
|
progressIndicator.style.display = 'none'; // 隐藏进度指示
|
|
|
uploadButton.disabled = false; // 启用按钮
|
|
|
if (data.status === 'success') {{
|
|
|
messageBox.innerHTML = '<p style="color:green;">' + data.message + '</p>';
|
|
|
updateFileList(data.files); // 更新文件列表
|
|
|
}} else {{
|
|
|
messageBox.innerHTML = '<p style="color:red;">' + data.message + '</p>';
|
|
|
}}
|
|
|
}})
|
|
|
.catch(error => {{
|
|
|
progressIndicator.style.display = 'none'; // 隐藏进度指示
|
|
|
uploadButton.disabled = false; // 启用按钮
|
|
|
messageBox.innerHTML = '<p style="color:red;">Upload failed</p>';
|
|
|
}});
|
|
|
}}
|
|
|
|
|
|
function updateFileList(files) {{
|
|
|
const filesListHtml = files.map(file => '<li>' + file + '</li>').join('');
|
|
|
document.getElementById('filesList').innerHTML = filesListHtml;
|
|
|
}}
|
|
|
|
|
|
function showAllFiles() {{
|
|
|
// 读取所有文件并显示
|
|
|
fetch('/upload')
|
|
|
.then(response => response.json())
|
|
|
.then(data => {{
|
|
|
if (data.files) {{
|
|
|
updateFileList(data.files); // 更新文件列表显示
|
|
|
document.getElementById('showMoreButton').style.display = 'none'; // 隐藏"查看全部"按钮
|
|
|
}}
|
|
|
}});
|
|
|
}}
|
|
|
</script>
|
|
|
</head>
|
|
|
<body>
|
|
|
<h1>Upload a file</h1>
|
|
|
<form id="uploadForm" onsubmit="uploadFile(event)" enctype="multipart/form-data">
|
|
|
<label for="customPath">Custom Path (default: {DEFAULT_UPLOAD_FOLDER}):</label>
|
|
|
<input type="text" id="customPath" name="customPath" placeholder="Enter absolute path (e.g., /mnt/self/)">
|
|
|
<input type="file" name="file" required>
|
|
|
<button id="uploadButton" type="submit">Upload</button>
|
|
|
<span id="progressIndicator" style="display:none;">Uploading...</span>
|
|
|
</form>
|
|
|
<div id="messageBox"></div>
|
|
|
<h2>Uploaded files (Latest files displayed):</h2>
|
|
|
<ul id="filesList">
|
|
|
{files_list_html}
|
|
|
{hidden_files_html}
|
|
|
</ul>
|
|
|
<button id="showMoreButton" onclick="showAllFiles()">Show All Files</button>
|
|
|
</body>
|
|
|
</html>
|
|
|
"""
|
|
|
return html_template
|
|
|
|
|
|
|
|
|
if __name__ == '__main__':
|
|
|
if not os.path.exists(DEFAULT_UPLOAD_FOLDER):
|
|
|
os.makedirs(DEFAULT_UPLOAD_FOLDER)
|
|
|
app.run(host='0.0.0.0', port=8066)
|