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

使用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;
}

关键修改说明

  1. 新增dataURLtoFile函数,将压缩后的DataURL转换为标准File对象
  2. 优化compressImage函数,优先降低压缩质量,质量不足时再缩小尺寸,减少画质损失
  3. 新增handleFileAndPreview统一处理逻辑,合并压缩、预览、文件替换
  4. 替换所有input的onchange事件为统一的处理函数,避免重复监听冲突
  5. 使用DataTransfer创建新的FileList替换input的原始文件,确保表单提交时上传的是压缩后的文件

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 19:48:10