图片 url、base64(dataURL)、blob 相互转化

2,507 阅读2分钟

url转base64

调用:

let imgUrL = `http://XXX.jpg`
this.getDataUri(imgUrL).then(res => {
  // 转化后的base64图片地址
  console.log('base64', res)
})
 // 原理: 利用canvas.toDataURL的API转化成base64
    
    urlToBase64(url) {
      return new Promise ((resolve,reject) => {
          let image = new Image();
          image.onload = function() {
            let canvas = document.createElement('canvas');
            canvas.width = this.naturalWidth;
            canvas.height = this.naturalHeight;
            // 将图片插入画布并开始绘制
            canvas.getContext('2d').drawImage(image, 0, 0);
            // result
            let result = canvas.toDataURL('image/png')
            resolve(result);
          };
          // CORS 策略,会存在跨域问题https://stackoverflow.com/questions/20424279/canvas-todataurl-securityerror
          image.setAttribute("crossOrigin",'Anonymous');
          image.src = url;
          // 图片加载失败的错误处理
          image.onerror = () => {
            reject(new Error('图片流异常'));
        };
    }

url转blob

调用:

imageDownload('https://cdn.segmentfault.com/v-5e154194/global/img/user-64.png')

支持本地或者页面图片:172.168.0.91:8080/app/imgs/avatar.png

canvas 不能处理跨域图片,如果要处理,除了服务端要开启跨域外,执行canvas操作前也要开启跨域:img.setAttribute("crossOrigin", 'Anonymous')。如果提示跨域,说明图片服务器不支持

const imageDownload = src = {
  let canvas = document.createElement('canvas')
  let img = document.createElement('img')
  img.onload = () => {
    canvas.width = img.width
    canvas.height = img.height
    let context = canvas.getContext('2d')
    context.drawImage(img, 0, 0, img.width, img.height)
    canvas.getContext('2d').drawImage(img, 0, 0, img.width, img.height)
    canvas.toBlob(blob => {
      let link = document.createElement('a')
      link.href = window.URL.createObjectURL(blob)
      link.download = 'download' // resource name
      link.click()
    }, "/*可指定图片格式*/", "0.95")
  }
  img.setAttribute("crossOrigin", 'Anonymous') //前端支持跨域
  img.src = src
}

base64转blob

调用

let base64 = base64.split(',')[1]
this.base64ToBlob({b64data: base64, contentType: 'image/png'}).then(res => {
    // 转后后的blob对象
    console.log('blob', res)
})
// 原理:利用URL.createObjectURL为blob对象创建临时的URL

  base64ToBlob ({b64data = '', contentType = '', sliceSize = 512} = {}) {
      return new Promise((resolve, reject) => {
        // 使用 atob() 方法将数据解码
        let byteCharacters = atob(b64data);
        let byteArrays = [];
        for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
          let slice = byteCharacters.slice(offset, offset + sliceSize);
          let byteNumbers = [];
          for (let i = 0; i < slice.length; i++) {
              byteNumbers.push(slice.charCodeAt(i));
          }
          // 8 位无符号整数值的类型化数组。内容将初始化为 0。
          // 如果无法分配请求数目的字节,则将引发异常。
          byteArrays.push(new Uint8Array(byteNumbers));
        }
        let result = new Blob(byteArrays, {
          type: contentType
        })
        result = Object.assign(result,{
          // jartto: 这里一定要处理一下 URL.createObjectURL
          preview: URL.createObjectURL(result),
          name: `图片示例.png`
        });
        resolve(result)
      })
   }

blob转base64

调用

this.blobToBase64(blob).then(res => {
    // 转化后的base64
    console.log('base64', res)
})
// 原理:利用fileReader的readAsDataURL,将blob转为base64
blobToBase64(blob) {
   return new Promise((resolve, reject) => {
     const fileReader = new FileReader();
     fileReader.onload = (e) => {
       resolve(e.target.result);
     };
     // readAsDataURL
     fileReader.readAsDataURL(blob);
     fileReader.onerror = () => {
       reject(new Error('文件流异常'));
     };
   });
}

base64转file

//base64 转成 File 对象
function base64toFile(dataurl, filename) {//将base64转换为文件
    var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
      bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
    while(n--){
      u8arr[n] = bstr.charCodeAt(n);
    }
    return new File([u8arr], filename, {type:mime});
 }

file转base64 通过fileReader

 convertFileToDataURLviaFileReader(url, callback) {
    const xhr = new XMLHttpRequest()
    xhr.responseType = 'blob'
    xhr.onload = function () {
        const reader = new FileReader()
        reader.onloadend = function () {
            callback(reader.result)
        }
        reader.readAsDataURL(xhr.response)
    }
    xhr.open('GET', url)
    xhr.send()
}

base64转blob

dataURLToBlob(dataurl) {
    console.log('datarul', dataurl)
    let arr = dataurl.split(','),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n)
    while (n--) {
        u8arr[n] = bstr.charCodeAt(n)
    }
    return new Blob([u8arr], { type: mime })
}