上一篇
html5图片压缩上传
- 行业动态
- 2025-05-11
- 6
利用HTML5 Canvas压缩图片,减小体积后上传
HTML5图片压缩上传实现方案
核心原理
通过HTML5的FileReader
读取图片二进制数据,结合Canvas
对图像进行缩放处理,利用toBlob
方法生成压缩后的图像文件,最终通过FormData
提交到服务器。
实现步骤
文件选择与读取
<input type="file" id="upload" accept="image/">
const fileInput = document.getElementById('upload'); fileInput.addEventListener('change', handleFile); function handleFile(e) { const file = e.target.files[0]; if (!file) return; const reader = new FileReader(); reader.onload = function(event) { const img = new Image(); img.onload = function() { compressImage(img, file.type); }; img.src = event.target.result; }; reader.readAsDataURL(file); }
图像压缩处理
function compressImage(img, type) { const canvas = document.createElement('canvas'); let width = img.width; let height = img.height; // 计算压缩尺寸(保持比例) if (width > 1000) { width = 1000; height = (img.height 1000) / img.width; } canvas.width = width; canvas.height = height; const ctx = canvas.getContext('2d'); ctx.drawImage(img, 0, 0, width, height); // 生成压缩文件 canvas.toBlob(function(blob) { uploadFile(blob, type); }, type || 'image/jpeg', 0.7); // 质量参数0-1 }
文件上传
function uploadFile(blob, type) { const form = new FormData(); form.append('file', blob, 'compressed.' + type.split('/')[1]); fetch('/upload', { method: 'POST', body: form, onUploadProgress: e => { console.log('上传进度:', Math.round(e.loaded 100 / e.total) + '%'); } }) .then(response => response.json()) .then(data => { alert('上传成功:' + data.url); }) .catch(err => { console.error('上传失败:', err); }); }
关键技术对比表
技术环节 | 传统方案 | HTML5方案 |
---|---|---|
文件读取 | 依赖后台接收原始文件 | FileReader 前端预处理 |
图像处理 | 服务器端ImageMagick等工具 | Canvas 客户端实时压缩 |
格式转换 | 后台转码耗时 | 前端toBlob 指定输出格式 |
进度反馈 | 页面刷新后显示 | onUploadProgress 实时进度条 |
兼容性处理 | IE需Flash插件 | 现代浏览器原生支持 |
问题与解答
Q1:如何动态调整压缩比例?
A1:在toBlob
方法中修改第二个参数(0-1数值),数值越小压缩率越高,可通过滑动条实时调整:
<input type="range" min="0.1" max="1" step="0.1" id="quality">
const quality = document.getElementById('quality').value; canvas.toBlob(callback, type, parseFloat(quality));
Q2:如何处理超过2GB的大文件?
A2:采用分片上传策略:
- 使用
slice
方法分割文件:file.slice(start, end)
- 逐片压缩并上传
- 合并分片(需服务器支持)
示例代码:const chunkSize = 5 1024 1024; // 5MB每片 let currentChunk = 0; while(currentChunk < file.size) { const chunk = file.slice(currentChunk, currentChunk+chunkSize); // 压缩并上传该片段... currentChunk += chunkSize;