【JS基础】Blob对象与base64

266 阅读4分钟

image.png

Blob对象

Blob 对象表示一个不可变、原始数据的类文件对象。它的数据可以按文本或二进制的格式进行读取,也可以转换成 ReadableStream 来用于数据操作。 

function downloadBlob(url){
    const xhr=new XMLHttpRequest();
    xhr.open('GET',url);
    xhr.responseType='blob';
    xhr.send();
    xhr.onload=function( ){
        const fileBlob=xhr.response;
        console.log(fileBlob);
    }
}

let url="./img.jpg";
downloadBlob(url)

// Blob {size: 62916, type: 'image/jpeg'}
// size: 62916
// type: "image/jpeg"
// [[Prototype]]: Blob
// arrayBuffer: ƒ arrayBuffer()
// 返回一个包含所有blob二进制内容的Promise
// size: (…)
// slice: ƒ slice()
// 返回一个新的Blob对象,包括了Blob指定范围内所有数据
// stream: ƒ stream()
// 返回一个能够读取blob内容的ReadableStream
// text: ƒ text()
//返回一个包括Blob所有内容的UTF-8编码的Promise
// type: (…)
// constructor: ƒ Blob()
// Symbol(Symbol.toStringTag): "Blob"
// get size: ƒ size()
// get type: ƒ type()
// [[Prototype]]: Object

Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

要从其他非blob对象和数据构造一个 Blob,请使用 Blob() 构造函数。要创建一个 blob 数据的子集 blob,请使用 slice() 方法。要获取用户文件系统上的文件对应的 Blob 对象,请参阅 File 文档。

接受 Blob 对象的API也被列在 File 文档中。

注意: slice() 方法原本接受 length 作为第二个参数,以表示复制到新 Blob 对象的字节数。如果设置的参数使 start + length 超出了源 Blob 对象的大小,则返回从开始到结尾的所有数据。

注意: slice() 方法在某些浏览器和版本上带有浏览器引擎前缀:比如 Firefox 12 及更早版本的blob.mozSlice() 和 Safari 中的blob.webkitSlice()。 没有浏览器引擎前缀的老版本 slice() 方法有不同的语义,并且已过时。Firefox 30 取消了对 blob.mozSlice() 的支持。

构造函数

属性

  • Blob.size 只读

    Blob 对象中所包含数据的大小(字节)。

  • Blob.type 只读

    一个字符串,表明该 Blob 对象所包含数据的 MIME 类型。如果类型未知,则该值为空字符串。

方法

image.png

应用

实现文件的下载

例如我们想提供图片的上传、下载、预览功能

image.png

文件的上传

 <input type="file" id="input"/>

直接通过一个input标签完成,然后我们 测试一下是否正常:

input.onchange=function(e){
   console.log(e.target.files[0])
   //File {name: 'f72c89a3-8237-47da-be46-
   //c47be50ddc6c.png', lastModified: 1649062190398,
   //lastModifiedDate: Mon Apr 04 2022 16:49:50 GMT+0800 //(中国标准时间), 
   //webkitRelativePath: '', size: 25, …}
}

文件的下载

html:

 <input type="file" id="input"/> 
   <a download href="#" id="download"></a>
   <button id="btn"> 下载</button>
   ```
   
   ```js
  let blob;
input.onchange=function(e){
   console.log(e.target.files[0]);
   blob=new Blob([e.target.files[0]],{
       type:"image/png"
   })
}

btn.onclick=async function(){
   const file=await blob;
   download.download="img.png";
   download.href=URL.createObjectURL(file);
   download.click();
}

图片的预览

图片的预览有两种方式,即同步与异步

同步方式

基本思想是创建一个image然后将其挂载到dom上

input.onchange=function(e){
    console.log(e.target.files[0]);
    const img=new Image();
    img.src=URL.createObjectURL(e.target.files[0]);
    document.body.appendChild(img);
    blob=new Blob([e.target.files[0]],{
        type:"image/png"
    })
    
}

image.png

异步方式

异步方式主要思想是使用FileReaderFileReader允许用户异步读取存储在用户计算机上的文件

input.onchange=function(e){
    console.log(e.target.files[0]);
    
    const img=new Image();
    const fileReader=new FileReader();
    document.body.appendChild(img);
    fileReader.onload=function(){
        img.src=fileReader.result;
    }
    fileReader.readAsDataURL(e.target.files[0]);
    blob=new Blob([e.target.files[0]],{
        type:"image/png"
    })
    
}

base64

Q1: base64 由哪 64 个字符构成 A1:A-Za-z0-9+/``A-Za-z0-9+/

Q2: 什么是 base64 与 URL Safe base64 A2: base64 由 0-9A-Za-z 及 +/ 组成,但是在 URL 中使用 base64 时,/ 容易与路径符号发生冲突 因此,URL Safe Base64 将 + 替换为 _/ 替换为 -

概念

Base64是一种基于64个可打印字符来表示二进制数据的表示方法。由于log264=6log _{2}64=6,所以每6个比特为一个单元,对应某个可打印字符。3个字节相当于24个比特,对应于4个Base64单元,即3个字节可由4个可打印字符来表示。在Base64中的可打印字符包括字母A-Z、a-z、数字0-9,这样共有62个字符,此外两个可打印符号在不同的系统中而不同。一些如uuencode的其他编码方法,和之后BinHex的版本使用不同的64字符集来代表6个二进制数字,但是不被称为Base64。 Base64常用于在通常处理文本数据的场合,表示、传输、存储一些二进制数据,包括MIME的电子邮件及XML的一些复杂数据。 ---维基百科

手写Base64编码

const str="this is a base64 case";

const str1=new Array(26).fill(65).map((item,index)=>String.fromCodePoint(item+index));
const base64Code=[...str1,...str1.map(item=>item.toLowerCase()),0,1,2,3,4,5,6,7,8,9,"+","/"]
console.log(base64Code)

function toBase64(str){
    let item="";
    let encode="";
    const temp=str;
    const code= temp.split("").reduce((prev,cur)=>prev+cur.charCodeAt(0)
        .toString(2).padStart(8,"0"),"");
    
    for (let i=0;i<code.length;i+=6){
        item=code.slice(i,i+6);
        item=item.length===6?item:item.padEnd(6,"0");
        encode+=base64Code[parseInt(item,2)];
    }

    return encode;
}

console.log(toBase64(str));
//dGhpcyBpcyBhIGJhc2U2NCBjYXNl

The End

image.png