You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何获取AJAX POST请求的进度?基于Python Flask API的实现咨询

如何在AJAX POST请求中获取上传/下载进度

没问题,我来帮你搞定这个进度监听的问题!你之前的代码其实只监听了下载进度——也就是服务器给你返回数据时的进度,所以只有等响应开始返回才会触发。如果要获取请求发送过程中的上传进度(比如你POST大表单、文件的时候),得监听xhr.upload对象的progress事件才行。

下面分两种常用场景给你实现建议:

一、jQuery $.ajax 实现

通过xhr选项自定义XMLHttpRequest对象,同时监听上传和下载进度:

$.ajax({
  url: '/your-flask-api-endpoint',
  method: 'POST',
  data: yourRequestData, // 如果是上传文件,这里传FormData对象
  processData: false,    // 上传文件必须设为false,禁止jQuery自动处理数据
  contentType: false,    // 上传文件时设为false,让浏览器自动生成正确的Content-Type
  xhr: function() {
    const xhr = new XMLHttpRequest();

    // 监听【上传进度】:发送请求数据到服务器的过程
    xhr.upload.addEventListener('progress', function(evt) {
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100;
        console.log(`上传进度:${percentComplete.toFixed(2)}%`);
        $('.progress').css({ width: `${percentComplete}%` });
      }
    }, false);

    // 监听【下载进度】:服务器返回响应数据的过程(就是你之前代码监听的事件)
    xhr.addEventListener('progress', function(evt) {
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100;
        console.log(`下载进度:${percentComplete.toFixed(2)}%`);
        // 可以单独更新下载进度条
      }
    }, false);

    // 请求完成后隐藏进度条
    xhr.addEventListener('loadend', function() {
      if ($('.progress').width() >= $('.progress').parent().width()) {
        $('.progress').addClass('hide');
      }
    }, false);

    return xhr;
  },
  success: function(res) {
    console.log('请求成功', res);
  },
  error: function(xhr, status, err) {
    console.error('请求失败', err);
  }
});

关键注意点:

  • 如果是上传文件,一定要设置processData: false和contentType: false,否则jQuery会把FormData转成字符串,导致文件上传失败。
  • lengthComputable为true才能计算进度:上传时要求发送的数据有明确的总长度(比如文件、FormData);下载时要求服务器在响应头里返回Content-Length。

二、AngularJS $http 实现

通过xhrFactory自定义XMLHttpRequest对象,添加进度监听:

$http({
  method: 'POST',
  url: '/your-flask-api-endpoint',
  data: yourRequestData, // 上传文件时传FormData对象
  headers: {
    // 上传文件时不要手动设置Content-Type,让浏览器自动生成带boundary的multipart/form-data
  },
  transformRequest: function(data, headersGetter) {
    // 如果是FormData,直接返回,避免Angular自动转换为JSON
    if (data instanceof FormData) {
      return data;
    }
    return $http.defaults.transformRequest[0](data, headersGetter);
  },
  xhrFactory: function() {
    const xhr = new XMLHttpRequest();

    // 监听上传进度
    xhr.upload.addEventListener('progress', function(evt) {
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100;
        console.log(`上传进度:${percentComplete.toFixed(2)}%`);
        // 更新Angular作用域的进度变量,记得触发digest
        $scope.$apply(() => {
          $scope.uploadProgress = percentComplete;
        });
      }
    }, false);

    // 监听下载进度
    xhr.addEventListener('progress', function(evt) {
      if (evt.lengthComputable) {
        const percentComplete = (evt.loaded / evt.total) * 100;
        console.log(`下载进度:${percentComplete.toFixed(2)}%`);
        $scope.$apply(() => {
          $scope.downloadProgress = percentComplete;
        });
      }
    }, false);

    return xhr;
  }
}).then(function(res) {
  console.log('请求成功', res.data);
  $scope.progressVisible = false;
}).catch(function(err) {
  console.error('请求失败', err);
});

关键注意点:

  • 因为进度事件是异步的,不属于Angular的digest周期,所以更新$scope变量时要调用$scope.$apply(),否则视图不会实时更新。
  • 同样,上传文件时不要手动设置Content-Type,否则会缺少boundary参数导致服务器无法解析文件。

三、Flask 后端的配合注意事项

  1. 如果处理大文件上传,需要在Flask配置里设置最大允许的请求大小:
    app.config['MAX_CONTENT_LENGTH'] = 32 * 1024 * 1024  # 限制为32MB
    
  2. 如果要让下载进度能正常计算,返回响应时要确保包含Content-Length头:
    • 使用send_file返回文件时,Flask会自动添加这个头;
    • 如果是动态生成的大响应,需要手动计算内容长度并设置头:
      response = make_response(large_content)
      response.headers['Content-Length'] = str(len(large_content))
      return response
      

内容的提问来源于stack exchange,提问作者Krishna

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 04:58:02