js blob对象互转

什么是Blob?
Blob 是什么? 这里说的是一种Javascript的对象类型。

oracle 中也有类似的栏位类型。

在 [JS进阶] HTML5 之文件操作(file)
这一篇中用到了File对象,而实际上 file 对象只是 blob 对象的一个更具体的版本,blob 存储着大量的二进制数据,并且 blob 的 size 和 type 属性,都会被 file 对象所继承。
所以, 在大多数情况下,blob 对象和 file 对象可以用在同一个地方,例如,可以使用 FileReader 接口从 blob 读取数据,也可以使用 URL.createObjectURL() 从 blob 创建一个新的 URL 对象。

如何创建Blob
1. 使用旧方法创建 Blob 对象。

旧的方法使用 BlobBuilder 来创建一个Blob 实例,并且使用一个 append() 方法,将字符串(或者 ArrayBuffer 或者 Blob,此处用 string 举例)插入,一旦数据插入成功,就可以使用 getBlob() 方法设置一个 mime 。

  <script>
    var builder = new BolbBuilder();
    builder.append("Hello World!");
    var blob = builder.getBlob("text/plain");
  </script>


2. 新方法创建Blob 对象

在新的方法中直接可以通过 Blob() 的构造函数来创建了。
构造函数,接受两个参数,第一个为一个数据序列,可以是任意格式的值,例如,任意数量的字符串,Blobs 以及 ArrayBuffers。第二个参数,是一个包含了两个属性的对象,其两个属性分别是:

type -- MIME 的类型。

endings -- 决定 append() 的数据格式,(数据中的 \n 如何被转换)可以取值为 "transparent" 或者 "native"(t* 的话不变,n* 的话按操作系统转换;t* 为默认) 。

  <script>
    var blob = new Blob(["Hello World!"],{type:"text/plain;charset=utf-8"});  // type:可以设置别的文件类型
  </script>

Blob的应用
1. 大文件分割 (slice() 方法)

slice() 方法接受三个参数,起始偏移量,结束偏移量,还有可选的 mime 类型。如果 mime 类型,没有设置,那么新的 Blob 对象的 mime 类型和父级一样。

当要上传大文件的时候,此方法非常有用,可以将大文件分割分段,然后各自上传,因为分割之后的 Blob 对象和原始的是独立存在的。

不过目前浏览器实现此方法还没有统一,火狐使用的是 mozSlice() ,Chrome 使用的是 webkitSlice() ,其他浏览器则正常的方式 slice() 

可以写一个兼容各浏览器的方法:

    function sliceBlob(blob, start, end, type) {
      type = type || blob.type;
      if (blob.mozSlice) {
          return blob.mozSlice(start, end, type);
      } else if (blob.webkitSlice) {
          return blob.webkitSlice(start, end type);
      } else {
          throw new Error("This doesn't work!");
      }
    }

Original  reference: http://blog.youkuaiyun.com/oscar999/article/details/36373183

2.  在Chrome 中指定下载的文件名;
具体可以参考:

Web 端 js 导出csv文件(使用a标签)

引用:https://blog.youkuaiyun.com/oscar999/article/details/16342699

前言

导出文件,使用最多的方式还是服务器端来处理。比如jsp 中使用response 的方式。

但是,有时候可能就想使用web 前端是否也可以把页面上的内容导出来呢? 比如说,导出页面的一个表格。

这个需求肯定是有答案的,只是对于各浏览器处理会稍微不一样。(主要是IE 和其他浏览器的区别)。

在IE中使用ActiveXObject 实现,在firefox 和Chrome 中使用  a 标签(或者js)就可以实现了。 这里主要讲一下其他浏览器中的实现。

 

使用 a 标签实现方式

直接上例子:

 

 
  1. <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">

  2. <html>

  3. <head>

  4. <meta http-equiv="content-type" content="text/html; charset=utf-8">

  5. <meta name="author" content="oscar999">

  6. <title></title>

  7. </head>

  8. <body>

  9. <a id="test" download="downlaod.txt" href="data:text/txt;charset=utf-8,download Test Data">download</a>

  10. </body>

  11. </html>

说明一下:

 

1. download 设置下载的文件名。

2. href 加上 data:text/txt;charset=utf-8  分别设置点击link 是下载文件, 编码是utf-8 . 这个逗号后面的就是保存在文件中的内容了。

 

以多行,多列导出csv 文件

csv 文件可以用Excel打开, 如果是导出一个table 的话,使用Excel 就方便很多了。

问题是: 如何分行, 分列?

理论上 : 分列使用 , 号分割, 分行用 \n .

可以用以上方式,会发现列可以分开,但是不换行。 看上去不认识 \n.

解决方式是使用 encodeURIComponent 进行编码/

 

 
  1. <head>

  2. <meta http-equiv="content-type" content="text/html; charset=utf-8">

  3. <meta name="author" content="oscar999">

  4. <title>

  5. </title>

  6. <script>

  7. function clickDownload(aLink)

  8. {

  9. var str = "col1,col2,col3\nvalue1,value2,value3";

  10. str = encodeURIComponent(str);

  11. aLink.href = "data:text/csv;charset=utf-8,"+str;

  12. aLink.click();

  13. }

  14. </script>

  15. </head>

  16. <body>

  17. <a id="test" onclick="clickDownload(this)" download="downlaod.csv" href="#">download</a>

  18. </body>

  19. </html>

 

 

带中文问题的csv 导出

以上使用的都是utf-8 编码,理论上导出中文应该不是问题。

但是导出csv 格式的话, 使用Excel 打开会发现中文是乱码,但是用其他文本程序打开确是正常的。

原因就是少了一个 BOM头  \ufeff。加上一切都正常了

  1.   <head>

  2.   <meta http-equiv="content-type" content="text/html; charset=gb2312">

  3.   <meta name="author" content="oscar999">

  4.   <title>

  5.   </title>

  6.   <script>

  7.     function clickDownload(aLink)

  8.     {

  9.          var str = "栏位1,栏位2,栏位3\n值1,值2,值3";

  10.          str =  encodeURIComponent(str);

  11.          aLink.href = "data:text/csv;charset=utf-8,\ufeff"+str; // \ufeff是关键

  12.          aLink.click();

  13.     }

  14.   </script>

  15.   </head>

  16.   <body>

  17.     <a id="test" onclick="clickDownload(this)" download="downlaod.csv" href="#">download</a>    

  18.   </body>

  19. </html>

这里有两个改变

1. 页面的charset 需设置成gb2312

2. 加上 \ufeff BOM 头

Chrome下载的文件名

以上使用 a 的download 属性可以指定下载的文件名及后缀。 但是在Chrome 执行的时候会发现, Chrome 压根不理会这个。

下载名是 "下载" 或是 "download".

上网搜索一下, 有说是Chrome 的 bug.

参见 stackoverflow 中的两篇文章:

http://stackoverflow.com/questions/23962284/download-attribute-on-a-tag-doesnt-work-in-chrome
http://stackoverflow.com/questions/23816005/anchor-tag-download-attribute-not-working-bug-in-chrome-35-0-1916-114

以上两篇文章可以不去关注, 需要关注的是这个问题是否可以解决, 以及解决的方法是什么?

直接贴解决方案:

  1. var blob = new Blob([data], { type: 'text/csv' }); //new way

  2. var csvUrl = URL.createObjectURL(blob);

  3. document.getElementById("mylink").href = csvUrl;

使用Blob 和URL 来封装和转换. 问题解决。

这里如遇中文问题, 和上面的处理方式是一样的:

1. 页面的charset 需设置成gb2312 (设成UTF-8 也可以)

2. 加上 \ufeff BOM 头

具体的代码类似:

  1. data = "\ufeff"+data;

  2. var blob = new Blob([data], { type: 'text/csv,charset=UTF-8'});

Brief summary:

以上为引用文,把内容合并了,希望助力大家开发。如有侵权请告知,会立即处理。

<think>我们正在处理一个关于JavaScript中将Blob对象换为Base64字符串的问题。 根据提供的引用,我们可以从引用[2]和引用[3]中找到相关方法。 引用[2]中提到:可以使用一个工具方法`blobToBase64`,它来自一个工具文件,使用方式如下: import { blobToBase64 } from '@/utils/xxx.js' blobToBase64(blob).then(res => { console.log(res) }).catch(err => { console.log(err) }) 引用[3]中有一个使用FileReader读取Blob(在例子中读取的是File,但File是Blob的子类)为base64的示例: var reader = new FileReader(); reader.readAsDataURL(tempFiles[0]); reader.onload = e => { this.byte_64 = e.target.result.split(';base64,')[1]; // 这里只获取了base64部分,去掉了前面的data:image/png;base64, }; 但是,我们通常需要的是整个DataURL(包括前面的MIME类型和base64编码)还是只要base64字符串?根据问题,用户要求换为Base64字符串,通常指的是去掉前缀的纯base64字符串(如引用[3]中的做法),但有时也可能需要整个DataURL。不过,问题中明确说“Base64字符串”,所以我们可以提供两种方式,并说明区别。 因此,我们可以自己编写一个函数,使用FileReader来读取Blob对象,并返回一个Promise,以便异步获取base64字符串。 步骤: 1. 创建一个FileReader对象。 2. 使用FileReader的readAsDataURL方法读取Blob对象。 3. 在onload事件中,获取读取结果(整个DataURL字符串)。如果只需要纯base64字符串,可以去掉前面的部分(如引用[3]中的split操作),或者也可以返回整个DataURL。 4. 使用Promise封装,因为读取操作是异步的。 根据用户需求,我们提供两种换: a) 返回整个DataURL(例如:"data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...") b) 返回纯base64字符串(例如:"iVBORw0KGgoAAAANSUhEUg...") 但问题中要求的是“Base64字符串”,通常指的是纯base64编码的字符串,所以我们将重点放在b)上。 实现: 我们可以写一个函数,返回一个Promise,当读取完成时,解析出纯base64字符串。 注意:引用[3]中通过split(';base64,')[1]来获取纯base64字符串,这是因为DataURL的格式是:`data:[<mediatype>][;base64],<data>`。 但是,我们也可以考虑返回整个DataURL,让用户自己决定如何处理。因此,我们可以提供两个函数,或者一个函数通过参数控制。 为了简单和明确,我们将分别实现两个函数: - blobToDataURL(blob): 返回DataURL字符串(包含前缀) - blobToBase64(blob): 返回纯base64字符串 然而,引用[2]中已经有一个名为`blobToBase64`的函数,它返回的是整个DataURL(因为在其示例中,使用`blobToBase64`返回的结果直接打印出来是DataURL,而他们又用了一个`base64ToBlob`来换,所以可能返回的是DataURL)。但是,在引用[2]的示例中,调用`blobToBase64`后打印的是base64,这有点矛盾?实际上,我们再看引用[2]的代码: blobToBase64(blob).then(res => { console.log(res) }) 这里打印的res,根据函数名应该是base64字符串,但根据引用[3]的经验,FileReader.readAsDataURL返回的是DataURL。所以,我们需要确认。 实际上,在引用[2]的代码中,他们的`blobToBase64`函数可能是返回DataURL,也可能是返回纯base64字符串?但他们的注释是“输出blob对象”,然后调用`blobToBase64`,所以这里不明确。 因此,我们按照标准做法: 使用FileReader.readAsDataURL得到的是DataURL字符串。如果我们想要纯base64字符串,需要去掉前面的部分。 所以,我们这样设计: 函数1:blobToDataURL(blob) 返回Promise,解析为完整的DataURL字符串。 函数2:blobToBase64(blob) 返回Promise,解析为纯base64字符串(去掉DataURL前缀)。 但是,我们也可以只提供一个函数,通过参数控制返回类型。但为了清晰,我们分开实现。 实现代码: 1. blobToDataURL(blob) 的实现: function blobToDataURL(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result); // reader.result就是DataURL reader.onerror = reject; reader.readAsDataURL(blob); }); } 2. blobToBase64(blob) 的实现: 我们可以利用上面的blobToDataURL,然后处理字符串,或者直接写: function blobToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { // 从DataURL中提取base64部分 const dataURL = reader.result; // 格式为:data:[<mediatype>][;base64],<data> // 我们找到逗号后面的部分 const base64 = dataURL.split(',')[1]; resolve(base64); }; reader.onerror = reject; reader.readAsDataURL(blob); }); } 但是,注意:split(',')[1]这种方法是否可靠?因为DataURL的格式是固定的,逗号前面是头部,后面是数据。所以这样分割是可行的。 另外,引用[3]中使用了split(';base64,'),这是因为他们知道有base64标记,但根据标准,DataURL的格式中,在base64编码的情况下,确实会有“;base64”标记。所以使用split(';base64,')也可以,但这样会包含分号,所以需要取第二部分。两种方法都可以,但split(',')更简单,因为逗号是数据部分的分隔符。 因此,我们采用split(',')的方法。 但是,注意:如果Blob对象不是通过base64编码的?实际上,readAsDataURL方法总是将数据编码为base64格式,并且生成标准的DataURL字符串,其中包含“;base64”标记。所以,使用split(',')取后半部分一定是base64字符串。 所以,我们可以这样写。 另外,我们也可以考虑错误处理。如果读取失败,Promise应该被reject。 现在,我们根据上述思路编写代码。 注意:我们也可以写一个函数,然后通过参数决定返回类型,但为了简单和符合引用[2]中的函数名,我们提供两个函数。 但是,引用[2]中的函数名是`blobToBase64`,它返回的是什么呢?从他们的示例中,调用`blobToBase64`后打印的是一个blob对象?这显然不对,因为注释说输出blob对象,但函数名是为base64。实际上,他们的示例可能是这样: const blob = base64ToBlob(base64, 'image/png') // 这个函数是base64字符串blob blobToBase64(blob) // 这个函数是blobbase64 然后他们打印了blob对象(在上一行),然后调用blobToBase64并打印结果(应该是base64字符串)。所以,我们按照函数名,我们的`blobToBase64`应该返回纯base64字符串?还是整个DataURL? 在引用[2]的示例中,他们调用`blobToBase64`后,在then回调中打印res,这个res应该是base64字符串(纯的)?还是DataURL?从他们的注释“输出图片base64”来看,应该是纯base64字符串,因为之前他们用`base64ToBlob`时传入的是纯base64字符串(没有DataURL前缀)。但注意,在`base64ToBlob`函数中,他们需要知道MIME类型,所以单独传了'image/png',而DataURL中是包含MIME类型的。 所以,我们这里有两种选择: a) 如果用户后续需要将base64字符串再Blob,那么需要知道MIME类型,所以返回DataURL(包含MIME类型)可能更方便,因为这样换回来时可以从DataURL中解析出MIME类型。 b) 如果用户只需要base64字符串,并且已经知道MIME类型(或者不需要),那么返回纯base64字符串。 因此,为了通用性,我们可以提供两种方式,并说明使用场景。 但是,用户的问题明确要求:“将Blob对象换为Base64字符串”,通常Base64字符串指的是纯的base64编码,不包含MIME类型。所以,我们主要提供纯base64字符串。 然而,在引用[3]中,他们获取了纯base64字符串,并存储起来,然后在上传时可能需要重新构建成DataURL或者通过multipart上传。所以,我们按照用户需求,提供纯base64字符串。 所以,我们实现`blobToBase64`函数返回纯base64字符串。 另外,我们也可以同时提供`blobToDataURL`,并在说明中解释。 现在,我们编写这两个函数,并给出使用示例。 注意:如果Blob很大,读取操作是异步的,所以使用Promise是合适的。 代码实现: ```javascript // 将Blob对象换为DataURL字符串(包含MIME类型和base64编码) function blobToDataURL(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = function() { resolve(reader.result); // reader.result是一个DataURL字符串 }; reader.onerror = function() { reject(reader.error); }; reader.readAsDataURL(blob); }); } // 将Blob对象换为纯base64字符串(去掉DataURL前缀) function blobToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = function() { // 从DataURL中分割出base64字符串 const dataURL = reader.result; // 格式: "data:[mediatype];base64,[base64数据]" // 我们使用逗号分割,取第二部分 const parts = dataURL.split(','); if (parts.length < 2) { reject(new Error('Invalid DataURL format')); return; } resolve(parts[1]); }; reader.onerror = function() { reject(reader.error); }; reader.readAsDataURL(blob); }); } ``` 使用示例: ```javascript // 假设有一个Blob对象,比如从canvas生成的图片Blob // 使用blobToBase64函数 blobToBase64(blob).then(base64String => { console.log(base64String); // 输出纯base64字符串 }).catch(error => { console.error('换失败', error); }); // 使用blobToDataURL函数 blobToDataURL(blob).then(dataURL => { console.log(dataURL); // 输出完整的DataURL }).catch(error => { console.error('换失败', error); }); ``` 另外,引用[2]中提到了一个工具文件,我们可以将这两个函数封装到一个工具模块中,以便复用。 最后,我们还要注意:在Node.js环境下没有FileReader,所以这些代码只能在浏览器环境中运行。 总结:我们提供了两种换方式,并给出了实现代码和使用示例。</think>### JavaScript中将Blob对象换为Base64字符串的方法 在JavaScript中,将Blob对象换为Base64字符串的核心方法是使用 **`FileReader` API**。以下是详细步骤和实现代码: #### 方法实现 ```javascript function blobToBase64(blob) { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => { // 从DataURL中提取纯Base64字符串(去掉"data:*;base64,"前缀) const base64 = reader.result.split(',')[1]; resolve(base64); }; reader.onerror = () => reject(reader.error); reader.readAsDataURL(blob); // 将Blob读取为DataURL }); } // 使用示例 const blob = new Blob(['Hello, World!'], { type: 'text/plain' }); blobToBase64(blob) .then(base64String => { console.log('Base64字符串:', base64String); // 输出: SGVsbG8sIFdvcmxkIQ== }) .catch(error => { console.error('换失败:', error); }); ``` #### 关键点说明 1. **`FileReader.readAsDataURL()`** 将Blob对象换为DataURL字符串,格式为: `data:<mediatype>;base64,<base64-data>` 例如:`data:text/plain;base64,SGVsbG8sIFdvcmxkIQ==` 2. **提取纯Base64字符串** 通过`split(',')[1]`移除DataURL的前缀,保留纯Base64编码部分。 3. **异步处理** 使用`Promise`封装异步操作,便于通过`.then()`或`async/await`处理结果。 #### 应用场景 - 图片上传前压缩预览 - 将二进制文件通过API传输 - 本地存储二进制数据(如IndexedDB) --- ### 相关问题 1. **如何将Base64字符串换回Blob对象?** ```javascript function base64ToBlob(base64, mimeType) { const byteString = atob(base64); const buffer = new Uint8Array(byteString.length); for (let i = 0; i < byteString.length; i++) { buffer[i] = byteString.charCodeAt(i); } return new Blob([buffer], { type: mimeType }); } ``` 2. **DataURL和纯Base64字符串有何区别?** - **DataURL**:完整格式`data:[<mediatype>][;base64],<data>`,可直接用于`<img src>`或下载链接。 - **纯Base64**:仅包含编码数据,需手动添加MIME类型才能使用[^3]。 3. **大文件换时如何避免内存溢出?** 使用流式处理(如`ReadableStream`)分块读取Blob,但浏览器支持有限,通常需后端配合。 4. **Blob换Base64的性能如何优化?** - 对于图片:先使用`canvas`压缩尺寸 - 分块处理:通过`blob.slice()`分割大文件 - Web Worker:避免阻塞主线程 [^1]: Blob与Base64互操作的核心API [^2]: 工具库封装示例 [^3]: DataURL结构解析 [^4]: 表单数据传输应用
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值