这是一个代码片段,我想做Blob到Base64字符串:

这个注释部分可以工作,当它生成的URL被设置为img src时,它会显示图像:

var blob = items[i].getAsFile();
//var URLObj = window.URL || window.webkitURL;
//var source = URLObj.createObjectURL(blob);
//console.log("image source=" + source);

var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)
}; // data url!
var source = reader.readAsBinaryString(blob);

问题在于较低的代码,生成的源变量为空

更新:

有一个更简单的方法来做到这一点与JQuery能够创建Base64字符串从Blob文件如在上面的代码?


当前回答

Typescript版本:

const blob2Base64 = (blob:Blob):Promise<string> => {
      return new Promise<string> ((resolve,reject)=> {
           const reader = new FileReader();
           reader.readAsDataURL(blob);
           reader.onload = () => resolve(reader.result.toString());
           reader.onerror = error => reject(error);
       })
      }

用法:

blob2Base64(blob).then(res=>console.log(res))

其他回答

var reader = new FileReader();
reader.readAsDataURL(blob); 
reader.onloadend = function() {
  var base64data = reader.result;                
  console.log(base64data);
}

将文档readAsDataURL编码为base64

作为一个可等待的函数:

function blobToBase64(blob) {
  return new Promise((resolve, _) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
    reader.readAsDataURL(blob);
  });
}

注意:如果不首先删除Base64编码数据之前的data - url声明,blob的结果不能直接解码为Base64。为了只检索Base64编码的字符串,首先从结果中删除data:/; Base64。

这招对我很管用:

var blobToBase64 = function(blob, callback) {
    var reader = new FileReader();
    reader.onload = function() {
        var dataUrl = reader.result;
        var base64 = dataUrl.split(',')[1];
        callback(base64);
    };
    reader.readAsDataURL(blob);
};

async TypeScript变体:

async function blobToBase64Async(blob: Blob): Promise<string> {
  return new Promise((resolve, reject) => {
    const fileReader = new FileReader();
    fileReader.onerror = (e) => reject(fileReader.error);
    fileReader.onloadend = (e) => {
      const dataUrl = fileReader.result as string;
      // remove "data:mime/type;base64," prefix from data url
      const base64 = dataUrl.substring(dataUrl.indexOf(',') + 1);
      resolve(base64);
    };
    fileReader.readAsDataURL(blob);
  });
}

示例用法:

async function fetchToBase64Async(url: string, init?: RequestInit): Promise<string> {
  try {
    const response = await fetch(url, init);
    if (!response.ok) {
      const responseText = await response.text();
      throw new Error("server status: " + response.status + "\n" + "server response:" + "\n" + responseText);
    }
    const blob = await response.blob();
    const base64 = await blobToBase64Async(blob);
    return base64;
  } catch (e) {
    throw new Error("failed to fetch: " + url + "\n" + "caused by: " + e);
  }
}

async function demoUsage() {
  const base64 = await fetchToBase64Async("https://httpstat.us/200", {
    method: "POST",
    headers: {
      "Accept": "*/*",
      "Authorization": "Bearer ...",
    }
  });
  console.log(base64);
}

注:

我不明白为什么有些答案使用load而不是loadend事件 我不明白为什么有些答案在设置事件处理程序之前调用readAsDataURL

来自@Arun Killu的答案是一个很好的片段,如果你知道发生了什么,但是没有人解释原始代码上的错误是什么。对于使用async和Promise调用的人来说,这个错误是很明显的,但对于正在学习或没有经验的人来说,就不那么清楚了。

这里有一个简单的解释。

糟糕的代码

var blob = items[i].getAsFile();

var reader = new FileReader();
reader.onload = function(event){
console.log(event.target.result)
}; // data url!
var source = reader.readAsBinaryString(blob);

上面的代码试图捕获源变量上的二进制字符串,但是FileReader.readAsBinaryString()返回undefined。这是因为无论何时触发onload事件,结果都是可用的。正如我们所看到的,他试图console.log event.target.result值,这是一个错误的方法。

好的代码

下面是一步一步的实现:

// 1. Create a FileReader instance
const reader = new FileReader()
// 2. Add a handler for the 'onload' event
reader.onload = (e) => {
    // 5. Get the result when the 'onload' event is triggered.
    const base64data = reader.result               
    console.log({base64data})
}
// 3. Add a handler for the 'onerror' event
reader.onerror = () => {                
    console.log('error')
}
// 4. Call 'readAsDataURL' method
reader.readAsDataURL(imageBlob) 

正如你所看到的,最后一步是5,这是因为它是一个异步调用。

下面是一个工作示例:

const url = 'https://i.stack.imgur.com/RRuCp.png' const fetchImage = async url => { const response = await fetch(url, {mode: 'no-cors',}) const blob = await response.blob() return blob } const loadImage = async () => { const imageBlob = await fetchImage(url) const reader = new FileReader() reader.onload = () => { const base64data = reader.result console.log({base64data}) } reader.onerror = () => { console.log('error') } reader.readAsDataURL(imageBlob) } loadImage()

Teo,异步是什么意思?

年轻的学徒,异步意味着我们不知道结果什么时候会准备好,它在每个系统中都是不同的,这取决于过程有多重或复杂,它也可以发现一些根本不会产生任何结果的错误。

因此,如果一个进程是异步的,使用async方法封装它是一个很好的实践,并返回一个像这样的Promise:

const blobToBase64 = async blob => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result)
    reader.error = (err) => reject(err)
    reader.readAsDataURL(blob)
  })
}

好吧,泰奥,但是什么是承诺?

小伙子,问得好。Promise对象表示异步操作的最终完成(或失败)及其结果值。换句话说,它会告诉我们结果是否准备好了,并会给我们它的值,否则会返回一个错误。

上面的代码显示了一个函数blobToBase64,它将返回一个Promise。这意味着这个函数将返回reader。结果当它准备好了。

如何将其集成到代码中?

超级简单,只需将所有FileReader替换为上面定义的函数blobToBase64并像这样调用它imageBase64 = await blobToBase64(imageBlob)

检查这个片段:

const url = 'https://i.stack.imgur.com/RRuCp.png' const fetchImage = async url => { const response = await fetch(url, { mode: 'no-cors', }) const blob = await response.blob() return blob } const blobToBase64 = async blob => { return new Promise((resolve, reject) => { const reader = new FileReader(); reader.onload = () => resolve(reader.result) reader.error = (err) => reject(err) reader.readAsDataURL(blob) }) } const loadImage = async() => { const imageBlob = await fetchImage(url) const imageBase64 = await blobToBase64(imageBlob) console.log({imageBase64}) } loadImage()

async function blobToBase64(blob) {
  return new Promise((resolve, _) => {
    const reader = new FileReader();
    reader.onloadend = () => resolve(reader.result);
    reader.readAsDataURL(blob);
  });
}

let blob = null; // <= your blob object goes here

blobToBase64(blob)
  .then(base64String => console.log(base64String));

参见:

https://gist.github.com/moosetraveller/723987931308c9ec63725c14cdcbc3e7