首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> 更多程式語言 >> 程式設計綜合問答

JavaScript 瀏覽器端圖片真實縮放並上傳:Canvas 處理完整指南

     編輯:程式設計綜合問答

核心誤區

修改 img.width/height 或 CSS 只改變顯示尺寸,FileReader 讀取的仍是原始檔案資料。要上傳縮放後的圖片,必須在 Canvas 繪製後提取 Blob/File。

標準流程

  1. input[type=file] 選取檔案
  2. FileReader.readAsDataURL → Image 載入
  3. 計算目標尺寸(等比縮放/固定寬高)
  4. canvas.width/height = 目標尺寸
  5. ctx.drawImage(img, 0, 0, 目標寬, 目標高)
  6. canvas.toBlob(callback, 'image/jpeg', 0.8) 獲取 Blob
  7. 構建 FormData 上傳

完整可用代碼


const input = document.getElementById('input_upload');
const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

input.addEventListener('change', async (e) => {
    const file = e.target.files[0];
    if (!file) return;

    // 1. 載入圖片
    const img = await loadImage(file);

    // 2. 計算縮放尺寸(例:最大 800px)
    const MAX_DIM = 800;
    let { width, height } = img;
    if (width > MAX_DIM || height > MAX_DIM) {
        const ratio = Math.min(MAX_DIM / width, MAX_DIM / height);
        width *= ratio;
        height *= ratio;
    }

    // 3. Canvas 繪製
    canvas.width = width;
    canvas.height = height;
    ctx.drawImage(img, 0, 0, width, height);

    // 4. 轉 Blob 並上傳
    const blob = await blobFromCanvas(canvas, 'image/jpeg', 0.85);
    await upload(blob, file.name);
});

function loadImage(file) {
    return new Promise((resolve, reject) => {
        const img = new Image();
        img.onload = () => resolve(img);
        img.onerror = reject;
        img.src = URL.createObjectURL(file); // 比 DataURL 更高效
    });
}

function blobFromCanvas(canvas, type, quality) {
    return new Promise(resolve => canvas.toBlob(resolve, type, quality));
}

async function upload(blob, filename) {
    const form = new FormData();
    form.append('file', blob, filename);
    const res = await fetch('/api/upload', { method: 'POST', body: form });
    console.log('上傳結果', await res.json());
}

關鍵優化點

優化說明
URL.createObjectURL避免 Base64 膨脹 33%,釋放時記得 URL.revokeObjectURL
EXIF 方向修正手機拍照常含 Orientation 標籤,需用 exif-js 讀取並旋轉 Canvas
分塊上傳大檔案 (>10MB) 採用 spark-md5 計算哈希 + 分片並發上傳
Web Worker將 Canvas 處理移至 Worker,不阻塞主執行緒
壓縮品質平衡0.7~0.9 之間視業務調整,過低產生伪影

進階:純前端多圖壓縮佇列


async function compressAll(files, options = {}) {
    const { maxDim = 1920, quality = 0.85, type = 'image/jpeg', concurrency = 2 } = options;
    const results = [];
    const queue = [...files];

    async function worker() {
        while (queue.length) {
            const file = queue.shift();
            const img = await loadImage(file);
            const { width, height } = calcDim(img, maxDim);
            const canvas = document.createElement('canvas');
            canvas.width = width; canvas.height = height;
            canvas.getContext('2d').drawImage(img, 0, 0, width, height);
            const blob = await blobFromCanvas(canvas, type, quality);
            results.push({ original: file, compressed: blob, width, height });
        }
    }

    await Promise.all(Array(concurrency).fill().map(worker));
    return results;
}

參考資源

掌握「載入 → 繪製 → 導出 Blob」三部曲,瀏覽器端即可實現專業級圖片預處理,大幅降低頻寬與伺服器壓力。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved