如何获取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 后端的配合注意事项
- 如果处理大文件上传,需要在Flask配置里设置最大允许的请求大小:
app.config['MAX_CONTENT_LENGTH'] = 32 * 1024 * 1024 # 限制为32MB - 如果要让下载进度能正常计算,返回响应时要确保包含
Content-Length头:- 使用
send_file返回文件时,Flask会自动添加这个头; - 如果是动态生成的大响应,需要手动计算内容长度并设置头:
response = make_response(large_content) response.headers['Content-Length'] = str(len(large_content)) return response
- 使用
内容的提问来源于stack exchange,提问作者Krishna
相关产品推荐
相关产品推荐

