如何结合AJAX Post使用browser-image-compression脚本实现图片压缩上传
图片压缩后AJAX上传失败问题解决
我是Javascript新手,想通过AJAX上传图片到服务器,但图片体积太大需要先压缩。找到browser-image-compression脚本后,折腾了5小时还是没成功——AJAX仍然传输原尺寸图片,控制台还报Uncaught (in promise) ReferenceError: compressedFile is not defined错误。
核心错误原因
- 异步执行顺序错误:
imageCompression是异步Promise操作,你的AJAX代码在它外部同步执行,此时压缩还没完成,compressedFile根本不存在,所以报错。 - 变量作用域问题:
compressedFile只在then回调函数内部有定义,外部代码无法访问这个变量。 - 语法错误:代码里
.then(function (compressedFile) {+多了一个多余的+号,会破坏代码结构。
修复方案
关键修复步骤
- 将AJAX上传代码完全移到
imageCompression的then回调内部,确保只有拿到压缩后的文件才执行上传。 - 移除回调函数开头多余的
+号。 - 可选:用
async/await改写代码,让异步逻辑更直观(适合新手理解)。
修正后的核心代码片段
// 替换原来的imageCompression及后续AJAX代码部分 const options = { maxWidthOrHeight: 1000, useWebWorker: true } imageCompression(original_file, options) .then(function (compressedFile) { console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); // true console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // 在这里创建FormData并执行AJAX上传 var filedata = new FormData(); filedata.append('game', game); filedata.append('data', image_type); filedata.append('input_val', "image"); filedata.append('file', compressedFile); $.ajax({ url: 'editimage.php', type: 'POST', data: filedata, dataType: "json", cache:false, contentType: false, processData: false, beforeSend: function() { var percentVal = '0%'; var percentVal2 = '0'; progress_bar.attr("aria-valuenow", percentVal2); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, uploadProgress: function(event, position, total, percentComplete) { var percentVal = percentComplete + '%'; progress_bar.attr("aria-valuenow", percentComplete); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, complete: function(xhr) { var percentVal = '100%'; var percentVal2 = '100'; progress_bar.attr("aria-valuenow", percentVal2); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, success: function(result){ if (result.status == true) { // 添加成功后的业务逻辑 } else { // 添加失败后的业务逻辑 } }, error: function(xhr, status, error) { console.error('上传失败:', error); } }); }) .catch(function (error) { console.error('压缩失败:', error.message); });
用async/await改写的版本(更易读)
如果你的环境支持ES6+,可以用async/await让代码逻辑更线性:
// 将then回调部分改成async函数形式 if(result.value){ var file_input = $('#gp-imageupload-fileElem'); var progress_bar = $('#gp-imageupload-progressbar'); var progress_percent = $('#gp-imageupload-progressbar-span'); var original_file = $('#gp-imageupload-fileElem')[0].files[0]; const options = { maxWidthOrHeight: 1000, useWebWorker: true }; try { // 等待压缩完成 const compressedFile = await imageCompression(original_file, options); console.log('compressedFile instanceof Blob', compressedFile instanceof Blob); console.log(`compressedFile size ${compressedFile.size / 1024 / 1024} MB`); // 构建表单数据 var filedata = new FormData(); filedata.append('game', game); filedata.append('data', image_type); filedata.append('input_val', "image"); filedata.append('file', compressedFile); // 执行AJAX上传 $.ajax({ url: 'editimage.php', type: 'POST', data: filedata, dataType: "json", cache:false, contentType: false, processData: false, beforeSend: function() { var percentVal = '0%'; var percentVal2 = '0'; progress_bar.attr("aria-valuenow", percentVal2); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, uploadProgress: function(event, position, total, percentComplete) { var percentVal = percentComplete + '%'; progress_bar.attr("aria-valuenow", percentComplete); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, complete: function(xhr) { var percentVal = '100%'; var percentVal2 = '100'; progress_bar.attr("aria-valuenow", percentVal2); progress_bar.css("width", percentVal); progress_percent.text(percentVal); }, success: function(result){ if (result.status == true) { // 添加成功后的业务逻辑 } else { // 添加失败后的业务逻辑 } }, error: function(xhr, status, error) { console.error('上传失败:', error); } }); } catch (error) { console.error('处理失败:', error.message); } }
内容的提问来源于stack exchange,提问作者David T Türkiye
相关产品推荐
相关产品推荐

