使用JavaScript在上传前将图片压缩至200KB失败求助
图片压缩后仍上传原始文件的问题解决
你的代码实现了图片压缩逻辑,但没有将压缩后的文件替换到文件输入框中,表单提交时依然会上传原始文件,这就是压缩功能看似生效但实际没作用的原因。
核心问题分析
- 压缩后的图片仅在回调里创建了新img元素,但没有关联到对应的文件输入框,表单提交时还是读取input的原始files
readURL系列函数直接读取原始文件显示,没有用压缩后的图片
解决步骤及修改后代码
以下是修复后的完整代码,主要调整了压缩后的文件替换逻辑和预览逻辑:
HTML部分(仅调整input的onchange事件)
<div class="col-sm-6"> <label class="form-label"><strong>ID Proof Front Photo:</strong></label> <img src="" alt="No Image" id="img1" style='height:150px; display:none;'> <button type="button" id="uploadFrontID" class="registerBtn" onblur="validateIDCardType(), validateFileTypeFront()" onclick="validateIDCardType(), selectFile('frontIDProof')"><img width="35" height="24" src="<?php echo $url; ?>assets/images/id1.svg"> <strong>Select Photo</strong></button> <input type='file' id="frontIDProof" name="uploadIDFrontPhoto" onchange="handleFileAndPreview('frontIDProof', 'img1')" style="display:none" accept="image/*" required /> <span id="photoFrontSpan" class="errSpan"></span> </div> <div class="col-sm-6"> <label class="form-label"><strong>ID Proof Back Photo:</strong></label> <img src="" alt="No Image" id="img2" style='height:150px; display:none;'> <button type="button" id="uploadBackID" class="registerBtn" onblur="validateFrontID(), validateIDCardType(), validateFileTypeBack()" onclick=" validateIDCardType(), selectFile('backIDProof')"><img width="35" height="24" src="<?php echo $url; ?>assets/images/id2.svg"> <strong>Select Photo</strong></button> <input type='file' id="backIDProof" name="uploadIDBackPhoto" style="display:none" onchange="handleFileAndPreview('backIDProof', 'img2')" accept="image/*" required /> <span id="photoBackSpan" class="errSpan"></span> </div> <div class="col-sm-6"> <label class="form-label"><strong>Profile Photo 1:</strong></label> <img src="" alt="No Image" id="img3" style='height:150px; display:none;'> <button type="button" id="profilePhoto1" class="registerBtn" onblur=" validateProfilePhoto1FileType()" onclick="selectFile('profilePhotoFile1')"><img width="24" height="24" src="<?php echo $url; ?>assets/images/photo1.svg"> <strong>Select Photo</strong></button> <input type='file' onchange="handleFileAndPreview('profilePhotoFile1', 'img3')" id="profilePhotoFile1" name="uploadPhoto1" style="display:none" accept="image/*" required /> <span id="photoSpan1" class="errSpan"></span> </div> <div class="col-sm-6"> <label class="form-label"><strong>Profile Photo 2:</strong></label> <img src="" alt="No Image" id="img4" style='height:150px; display:none;'> <button type="button" id="profilePhoto2" class="registerBtn" onblur="validateProfilePhoto2FileType()" onclick="selectFile('profilePhotoFile2')"><img width="24" height="24" src="<?php echo $url; ?>assets/images/photo2.svg"> <strong>Select Photo</strong></button> <input type='file' id="profilePhotoFile2" onchange="handleFileAndPreview('profilePhotoFile2', 'img4')" name="uploadPhoto2" style="display:none" accept="image/*"/> <span id="photoSpan2" class="errSpan"></span> </div> <div class="col-sm-6"> <label class="form-label"><strong>Profile Photo 3:</strong></label> <img src="" alt="No Image" id="img5" style='height:150px; display:none;'> <button type="button" id="profilePhoto3" class="registerBtn" onblur="validateProfilePhoto3FileType()" onclick="selectFile('profilePhotoFile3')"><img width="24" height="24" src="<?php echo $url; ?>assets/images/photo3.svg"> <strong>Select Photo</strong></button> <input type='file' id="profilePhotoFile3" name="uploadPhoto3" onchange="handleFileAndPreview('profilePhotoFile3', 'img5')" style="display:none" accept="image/*"/> <span id="photoSpan3" class="errSpan"></span> </div>
JavaScript部分
function selectFile(inputId) { document.getElementById(inputId).click(); } // 将DataURL转换为File对象 function dataURLtoFile(dataUrl, filename) { const arr = dataUrl.split(','); const mime = arr[0].match(/:(.*?);/)[1]; const bstr = atob(arr[1]); let n = bstr.length; const u8arr = new Uint8Array(n); while(n--) { u8arr[n] = bstr.charCodeAt(n); } return new File([u8arr], filename, {type: mime}); } function compressImage(file, maxSizeKB, callback) { const reader = new FileReader(); reader.onload = function(event) { const img = new Image(); img.onload = function() { let canvas = document.createElement('canvas'); let ctx = canvas.getContext('2d'); // 初始画布尺寸与原图一致 canvas.width = img.width; canvas.height = img.height; ctx.drawImage(img, 0, 0); let compressedDataUrl; let scaleFactor = 0.9; let quality = 0.7; // 初始压缩质量 do { // 根据文件类型选择压缩格式 let dataUrl = canvas.toDataURL(file.type === 'image/png' ? 'image/png' : 'image/jpeg', quality); const fileSizeKB = Math.round(dataUrl.length / 1024); if (fileSizeKB <= maxSizeKB) { compressedDataUrl = dataUrl; break; } // 先降低质量,质量到0.1后再缩小尺寸 if (quality > 0.1) { quality -= 0.1; } else { // 缩小画布尺寸 scaleFactor *= 0.9; canvas.width *= scaleFactor; canvas.height *= scaleFactor; ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, canvas.width, canvas.height); } } while (scaleFactor > 0.1); callback(compressedDataUrl); } img.src = event.target.result; } reader.readAsDataURL(file); } // 统一处理文件选择、压缩、预览和替换input文件 function handleFileAndPreview(inputId, previewImgId) { const input = document.getElementById(inputId); const file = input.files[0]; if (!file) return; const maxSizeKB = 200; compressImage(file, maxSizeKB, function(compressedDataUrl) { // 更新预览图 const previewImg = document.getElementById(previewImgId); previewImg.src = compressedDataUrl; previewImg.style.display = 'block'; // 将压缩后的DataURL转为File对象,替换input的原始文件 const compressedFile = dataURLtoFile(compressedDataUrl, file.name); // 创建新的FileList替换原input的files const newFileList = new DataTransfer(); newFileList.items.add(compressedFile); input.files = newFileList.files; }); } function enableDisableButton() { document.getElementById('regBtn').disabled = !document.getElementById('terms').checked; }
关键修改说明
- 新增
dataURLtoFile函数,将压缩后的DataURL转换为标准File对象 - 优化
compressImage函数,优先降低压缩质量,质量不足时再缩小尺寸,减少画质损失 - 新增
handleFileAndPreview统一处理逻辑,合并压缩、预览、文件替换 - 替换所有input的onchange事件为统一的处理函数,避免重复监听冲突
- 使用
DataTransfer创建新的FileList替换input的原始文件,确保表单提交时上传的是压缩后的文件
内容的提问来源于stack exchange,提问作者Purushottam Patil
相关产品推荐
相关产品推荐

