目标:在 Python (WSGI) 环境中实现 AJAX 上传功能,而无需使用 Flash 或 Silverlight,并且能够在上传过程中显示进度条。
- 当前环境:网站目前运行在 Werkzeug 框架附带的独立 wsgi 服务器上,但如果负载增加,可能会迁移至 mod_wsgi。
- 挑战:尝试过 gp.fileupload 中间件,但无法使其正常工作。官网上的示例也无法正常运行。
- 要求:网站已经使用了 Glow 库来处理其他客户端相关任务,但该库中并没有专门针对文件上传的功能。
2. 解决方案
- 使用 PythonWSGI 框架。
- 使用 JavaScript 来创建上传表单,其中包含一个带有“选择文件”按钮的文件选择控件。
- 使用 JavaScript 来侦听文件选择控件的“change”事件,并将所选文件发送到服务器。
- 在服务器端,处理文件上传请求,并将收到文件的名称和内容存储在数据库中。
- 使用 JavaScript 来轮询服务器,以查看上传进度。
- 当上传完成时,使用 JavaScript 来显示一条上传成功的消息。
// 创建上传表单
var form = document.createElement('form');
form.setAttribute('action', '/upload');
form.setAttribute('method', 'POST');
// 创建文件选择控件
var fileInput = document.createElement('input');
fileInput.setAttribute('type', 'file');
// 创建“选择文件”按钮
var submitButton = document.createElement('button');
submitButton.setAttribute('type', 'submit');
submitButton.innerHTML = '选择文件';
// 将文件选择控件和“选择文件”按钮添加到表单中
form.appendChild(fileInput);
form.appendChild(submitButton);
// 将表单添加到页面中
document.body.appendChild(form);
// 侦听文件选择控件的“change”事件
fileInput.addEventListener('change', function() {
// 获取所选文件
var files = this.files;
// 创建 FormData 对象
var formData = new FormData();
// 将所选文件添加到 FormData 对象中
formData.append('file', files[0]);
// 发送文件上传请求
var xhr = new XMLHttpRequest();
xhr.open('POST', '/upload', true);
xhr.send(formData);
// 轮询服务器,以查看上传进度
var intervalId = setInterval(function() {
// 获取上传进度的 JSON 数据
var progressData = JSON.parse(xhr.responseText);
// 显示上传进度
var progress = document.createElement('div');
progress.innerHTML = progressData.progress + '%';
document.body.appendChild(progress);
// 如果上传完成,则清除轮询间隔
if (progressData.progress === 100) {
clearInterval(intervalId);
// 显示上传成功的消息
var successMessage = document.createElement('div');
successMessage.innerHTML = '文件上传成功!';
document.body.appendChild(successMessage);
}
}, 1000);
});
# 导入必要的库
from flask import Flask, request, redirect, url_for
# 创建 Flask 应用
app = Flask(__name__)
# 定义上传文件的处理函数
@app.route('/upload', methods=['POST'])
def upload_file():
# 获取上传的文件
file = request.files['file']
# 保存文件到磁盘
file.save(os.path.join('uploads', file.filename))
# 返回上传成功的结果
return redirect(url_for('success'))
# 定义上传成功的处理函数
@app.route('/success')
def success():
# 显示上传成功的消息
return '文件上传成功!'
# 启动 Flask 应用
if __name__ == '__main__':
app.run()