实现 AJAX 上传,并带有进度条

95 阅读2分钟

目标:在 Python (WSGI) 环境中实现 AJAX 上传功能,而无需使用 Flash 或 Silverlight,并且能够在上传过程中显示进度条。

  • 当前环境:网站目前运行在 Werkzeug 框架附带的独立 wsgi 服务器上,但如果负载增加,可能会迁移至 mod_wsgi。
  • 挑战:尝试过 gp.fileupload 中间件,但无法使其正常工作。官网上的示例也无法正常运行。
  • 要求:网站已经使用了 Glow 库来处理其他客户端相关任务,但该库中并没有专门针对文件上传的功能。

huake_00183_.jpg 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()