HTML5 王者对象:Blob 的终极指南 🚀

301 阅读3分钟

二进制数据操作从未如此简单! 掌握 Blob 对象,解锁前端文件处理超能力!⚡️

Blob(Binary Large Object)是 HTML5 提供的二进制数据容器,让你直接在浏览器中操作文件数据,无需服务器中转!🔧


一、图片 → Base64 → Blob 全流程 📸🔄

// 1. 图片转 Base64
function imageToBase64(img) {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  
  return canvas.toDataURL('image/jpeg', 0.8); // 80%质量压缩
}

// 2. Base64 转 Blob
function base64ToBlob(base64, mimeType) {
  // 剥离 Base64 前缀
  const byteString = atob(base64.split(',')[1]);
  
  // 创建 Uint8Array
  const byteArray = new Uint8Array(byteString.length);
  for (let i = 0; i < byteString.length; i++) {
    byteArray[i] = byteString.charCodeAt(i);
  }
  
  // 生成 Blob
  return new Blob([byteArray], { type: mimeType });
}

// 使用示例
const img = document.getElementById('myImage');
const base64 = imageToBase64(img);
const blob = base64ToBlob(base64, 'image/jpeg');

二、Blob 核心操作:切割与压缩 ✂️💾

// 1. 切割大文件(如分片上传)
const sliceBlob = (blob, chunkSize = 1024 * 1024) => {
  const chunks = [];
  let start = 0;
  
  while (start < blob.size) {
    chunks.push(blob.slice(start, start + chunkSize));
    start += chunkSize;
  }
  
  return chunks;
};

// 2. 图片压缩(质量+尺寸)
async function compressImage(blob, maxWidth = 800, quality = 0.7) {
  return new Promise((resolve) => {
    const img = new Image();
    const url = URL.createObjectURL(blob);
    
    img.onload = () => {
      const canvas = document.createElement('canvas');
      const scale = maxWidth / img.width;
      canvas.width = maxWidth;
      canvas.height = img.height * scale;
      
      canvas.getContext('2d').drawImage(img, 0, 0, canvas.width, canvas.height);
      
      // 转回Blob
      canvas.toBlob(
        compressedBlob => resolve(compressedBlob), 
        'image/jpeg', 
        quality
      );
      
      URL.revokeObjectURL(url); // 释放内存
    };
    
    img.src = url;
  });
}

三、临时 URL:浏览器中的文件高速公路 🚗💨

// 1. 创建临时访问链接
const createTempUrl = (blob) => {
  return URL.createObjectURL(blob);
};

// 2. 应用场景:图片预览
const previewImage = document.getElementById('preview');
const fileInput = document.getElementById('upload');

fileInput.addEventListener('change', (e) => {
  const blob = e.target.files[0];
  previewImage.src = createTempUrl(blob);
});

// 3. 应用场景:文件下载
function downloadBlob(blob, filename) {
  const link = document.createElement('a');
  link.href = createTempUrl(blob);
  link.download = filename;
  document.body.appendChild(link);
  link.click();
  setTimeout(() => URL.revokeObjectURL(link.href), 100); // 延迟释放
}

四、Blob 实战应用:Excel 文件生成 📊💼

function exportToExcel(data) {
  // CSV 内容生成
  let csvContent = "名称,价格,库存
";
  data.forEach(row => {
    csvContent += `${row.name},${row.price},${row.stock}
`;
  });

  // 转Blob
  const blob = new Blob(["\uFEFF" + csvContent], { 
    type: 'text/csv;charset=utf-8' 
  });

  // 触发下载
  downloadBlob(blob, '产品数据.csv');
}

// 使用示例
const products = [
  { name: "手机", price: 3999, stock: 100 },
  { name: "笔记本", price: 8999, stock: 50 }
];
exportToExcel(products);

五、Blob 性能优化与陷阱 🚨

  1. 内存管理黄金法则 💡

    // 创建URL后必须释放!
    const url = URL.createObjectURL(blob);
    
    // 使用完成后立即释放
    const release = () => URL.revokeObjectURL(url);
    
    // 图片加载后释放
    img.onload = release;
    
  2. 大文件处理技巧 ⚙️

    // 使用Streams API处理超大文件
    async function processBigFile(blob) {
      const stream = blob.stream();
      const reader = stream.getReader();
      
      while (true) {
        const { done, value } = await reader.read();
        if (done) break;
        
        // 处理每个分块
        console.log('收到分块:', value.byteLength, 'bytes');
      }
    }
    

六、Blob 现代应用场景 🌍

  1. WebRTC 视频传输 📹

    // 录制视频片段
    const recorder = new MediaRecorder(stream);
    const chunks = [];
    
    recorder.ondataavailable = e => chunks.push(e.data);
    recorder.onstop = () => {
      const videoBlob = new Blob(chunks, { type: 'video/webm' });
      // 上传或预览
    };
    
  2. PWA 离线文件缓存 📂

    // 缓存二进制资源
    caches.open('v1').then(cache => {
      cache.put('/data.zip', new Response(blob));
    });
    

进阶技巧:Blob + Service Worker = 💪

// Service Worker中拦截请求并返回Blob
self.addEventListener('fetch', event => {
  if (event.request.url.endsWith('/dynamic-image')) {
    event.respondWith(
      fetch('/placeholder.jpg')
        .then(res => res.blob())
        .then(blob => {
          // 动态修改图片
          return modifyImage(blob); 
        })
        .then(modifiedBlob => {
          return new Response(modifiedBlob);
        })
    );
  }
});

Blob 使用三原则
1️⃣ 用完立即释放内存 (revokeObjectURL)
2️⃣ 大文件使用分片处理
3️⃣ 优先使用 Streams API 替代完整加载

掌握 Blob 对象,你将能在浏览器中完成以前必须依赖服务器的复杂文件操作,真正实现“浏览器即操作系统”的终极理念!🎯

【思考题】如何用 Blob 实现客户端加密文件后再上传?欢迎在评论区分享你的方案!🛠️