Blob 居然这么强大 作者: ciniao 时间: 2026-01-14 分类: AI文摘 ## 一、Blob 的本质与定义 Blob(Binary Large Object)是浏览器中的二进制大对象,File 对象实际上是 Blob 的一种特殊类型。通过简单代码即可创建: ```javascript const simpleBlob = new Blob(['Hello, World!'], { type: 'text/plain' }) ``` ## 二、Blob 的核心应用场景 ### 场景1:图片压缩上传 用户上传大尺寸图片时,前端可先压缩再上传,避免"文件太大"的错误反馈。 **实现原理:** 1. 使用 FileReader 读取图片 2. 通过 Canvas 进行缩放和重绘 3. 使用 canvas.toBlob() 生成压缩后的 Blob 4. 将压缩后的 Blob 通过 FormData 上传 **关键代码示例:** ```javascript async function compressImage(file, maxWidth = 800, quality = 0.7) { return new Promise((resolve) => { const reader = new FileReader() reader.readAsDataURL(file) reader.onload = (e) => { const img = new Image() img.src = e.target.result img.onload = () => { const canvas = document.createElement('canvas') const ctx = canvas.getContext('2d') // 计算等比例缩放 let width = img.width let height = img.height if (width > maxWidth) { height = (maxWidth / width) * height width = maxWidth } canvas.width = width canvas.height = height ctx.drawImage(img, 0, 0, width, height) // canvas转Blob canvas.toBlob( (blob) => resolve(blob), 'image/jpeg', quality ) } } }) } ``` ### 场景2:大文件分片上传 实现 2GB 大文件的分片上传,支持断点续传。 **核心技术:** - 使用 `Blob.slice()` 方法切割大文件 - 默认分片大小为 1MB - 支持从失败分片处继续上传 **实现要点:** ```javascript class BigFileUploader { constructor(file, chunkSize = 1024 * 1024) { this.file = file this.chunkSize = chunkSize this.totalChunks = Math.ceil(file.size / chunkSize) this.currentChunk = 0 } async upload() { while (this.currentChunk < this.totalChunks) { const start = this.currentChunk * this.chunkSize const end = Math.min(start + this.chunkSize, this.file.size) // 关键:用slice切割Blob const chunk = this.file.slice(start, end) const formData = new FormData() formData.append('chunk', chunk) formData.append('chunkIndex', this.currentChunk) formData.append('totalChunks', this.totalChunks) formData.append('fileName', this.file.name) try { await fetch('/api/upload-chunk', { method: 'POST', body: formData }) this.currentChunk++ // 更新进度条 const progress = (this.currentChunk / this.totalChunks) * 100 this.updateProgress(progress) } catch (error) { console.log('上传失败,但可以从当前分片续传') break } } } } ``` ### 场景3:前端生成文件并下载 用户填写表格后,前端直接生成 CSV 文件供下载。 **核心方法:** ```javascript function downloadCSV(data, filename = 'data.csv') { // 准备CSV内容 let csvContent = '' // 添加表头 const headers = Object.keys(data[0]) csvContent += headers.join(',') + '\n' // 添加数据行 data.forEach(row => { const values = headers.map(header => { const value = row[header] return `"${value}"` // 用引号包裹,避免逗号问题 }) csvContent += values.join(',') + '\n' }) // 创建Blob const blob = new Blob([csvContent], {type: 'text/csv;charset=utf-8;'}) // 创建下载链接 const link = document.createElement('a') const url = URL.createObjectURL(blob) link.href = url link.download = filename link.style.display = 'none' document.body.appendChild(link) link.click() // 清理 setTimeout(() => { document.body.removeChild(link) URL.revokeObjectURL(url) }, 100) } ``` ## 三、Blob 的高级应用 ### 1. 视频流处理 实现视频的流式播放,避免长时间加载: ```javascript async function streamVideo(videoUrl, videoElement) { const response = await fetch(videoUrl) const reader = response.body.getReader() const stream = new ReadableStream({ start(controller) { function push() { reader.read().then(({ done, value }) => { if (done) { controller.close() return } // 将数据块转为Blob const blob = new Blob([value]) const blobUrl = URL.createObjectURL(blob) // 动态更新视频源 videoElement.src = blobUrl controller.enqueue(value) push() }) } push() } }) } ``` ### 2. 浏览器数据库存储 在 IndexedDB 中存储文件: ```javascript async function saveFileToDB(file) { return new Promise((resolve, reject) => { const request = indexedDB.open('myFiles', 1) request.onupgradeneeded = (e) => { const db = e.target.result if (!db.objectStoreNames.contains('files')) { db.createObjectStore('files') } } request.onsuccess = (e) => { const db = e.target.result const transaction = db.transaction(['files'], 'readwrite') const store = transaction.objectStore('files') store.put(file, file.name) resolve() } request.onerror = reject }) } ``` ## 四、性能与安全注意事项 ### 1. 内存管理 使用 Blob URL 后必须释放内存: ```javascript // 创建Blob URL const blob = new Blob(['一些大数据']) const blobUrl = URL.createObjectURL(blob) // 使用... // 用完一定要释放! URL.revokeObjectURL(blobUrl) ``` ### 2. 安全限制 - **同源策略**:Blob URL 遵循同源策略 - **大小限制**:不同浏览器有不同的内存限制 - **类型验证**:浏览器会检查 MIME 类型是否匹配内容 ## 五、图片压缩工具的完整实现 ### 核心功能模块 1. **图片上传与预览**:使用 FileReader 将图片转为 Data URL 进行预览 2. **Canvas 压缩处理**:通过 canvas.toBlob() 生成压缩后的 Blob 3. **压缩后下载**:使用 URL.createObjectURL() 创建临时链接实现下载 ### 性能优化建议 1. **压缩参数设置**: - 质量:80% 是最佳平衡点 - 最大宽度:800px 适合网页展示,1920px 适合高清需求 2. **大图片处理策略**: ```javascript function processLargeImage(file) { const chunkSize = 1024 * 1024 // 每次处理1MB const totalChunks = Math.ceil(file.size / chunkSize) for (let i = 0; i < totalChunks; i++) { const chunk = file.slice(i * chunkSize, (i + 1) * chunkSize) // 处理每个分块... } } ``` ## 六、扩展功能与兼容性 ### 支持的图片格式扩展 ```javascript function getOutputFormat(originalType) { if (originalType === 'image/png') return 'image/png' if (originalType === 'image/webp') return 'image/webp' return 'image/jpeg' // 默认 } ``` ### 批量压缩处理 ```javascript async function batchCompress(files) { const compressedBlobs = [] for (const file of files) { const compressed = await compressImage(file, 80, 800) compressedBlobs.push(compressed.blob) } return compressedBlobs } ``` ## 七、应用场景总结 1. **用户头像上传**:先压缩再上传,节省服务器带宽 2. **内容管理系统**:编辑文章时压缩配图 3. **移动端拍照上传**:手机拍摄的照片通常很大,前端压缩后再传 4. **图床工具**:压缩后上传到图床,提高加载速度 ## 八、重要注意事项 1. **兼容性问题**:`canvas.toBlob()` 在 IE 中需要 polyfill 支持 2. **EXIF 信息丢失**:压缩后会丢失图片的拍摄信息 3. **透明背景处理**:转为 标签: none
评论已关闭