将blob转换为base64

xyb*_*rek 109 javascript jquery

这是我要BlobBase64字符串执行的代码的代码段:

这个注释部分有效,当由此生成的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);
Run Code Online (Sandbox Code Playgroud)

问题是代码越低,生成的源变量为null

更新:

有没有更简单的方法来使用JQuery从Blob文件创建Base64字符串,如上面的代码?

Aru*_*llu 228

 var reader = new FileReader();
 reader.readAsDataURL(blob); 
 reader.onloadend = function() {
     var base64data = reader.result;                
     console.log(base64data);
 }
Run Code Online (Sandbox Code Playgroud)

文档 readAsDataURL编码形式为base64

  • console.log(base64data.substr(base64data.indexOf(',')+ 1)); (23认同)
  • `onloadend`应该在`readAsDataURL`之前出现,以防万一发生奇怪的事情并在它到达下一行代码之前完成加载.显然这种情况永远不会发生,但它仍然是一种很好的做法. (6认同)
  • 输出的字符串看起来不像base64? (3认同)
  • 这个答案是不正确的,它在字符串的前面附加了none-base64字符。 (2认同)

Ame*_*icA 28

有一种不依赖于任何堆栈的纯 JavaSript 方式:

const blobToBase64 = blob => {
  const reader = new FileReader();
  reader.readAsDataURL(blob);
  return new Promise(resolve => {
    reader.onloadend = () => {
      resolve(reader.result);
    };
  });
};
Run Code Online (Sandbox Code Playgroud)

要使用此辅助函数,您应该设置一个回调,例如:

blobToBase64(blobData).then(res => {
  // do what you wanna do
  console.log(res); // res is base64 now
});
Run Code Online (Sandbox Code Playgroud)

我为 React Native 项目中的问题编写了这个辅助函数,我想下载一个图像,然后将其存储为缓存图像:

fetch(imageAddressAsStringValue)
  .then(res => res.blob())
  .then(blobToBase64)
  .then(finalResult => { 
    storeOnMyLocalDatabase(finalResult);
  });
Run Code Online (Sandbox Code Playgroud)


yea*_*xon 27

这对我有用:

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);
};
Run Code Online (Sandbox Code Playgroud)


小智 7

var audioURL = window.URL.createObjectURL(blob);
audio.src = audioURL;

var reader = new window.FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
     base64data = reader.result;
     console.log(base64data);
}
Run Code Online (Sandbox Code Playgroud)


Tho*_*ler 7

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));
Run Code Online (Sandbox Code Playgroud)

也可以看看:


Val*_*len 6

function bufferToBinaryString(arrayBuffer){
    return String.fromCharCode(...new Uint8Array(arrayBuffer));
}
(async () => console.log(btoa(bufferToBinaryString(await new Response(blob).arrayBuffer()))))();
Run Code Online (Sandbox Code Playgroud)

或者

function bufferToBinaryString(arrayBuffer){
    return String.fromCharCode(...new Uint8Array(arrayBuffer));
}
new Response(blob).arrayBuffer().then(arr_buf => console.log(btoa(bufferToBinaryString(arr_buf)))))
Run Code Online (Sandbox Code Playgroud)

参见Response 的构造函数,您可以将其[blob, buffer source form data, readable stream, etc.]转换为Response,然后可以将其转换[json, text, array buffer, blob]为异步方法/回调。

编辑:正如@Ralph 提到的,将所有内容转换为 utf-8 字符串会导致问题(不幸的是,响应 API 没有提供转换为二进制字符串的方法),因此使用数组缓冲区作为中间值,这需要另外两个步骤(将其转换为字节数组 THEN 到二进制字符串),如果你坚持使用本机btoa方法。


Ret*_*ner 6

异步 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);
  });
}
Run Code Online (Sandbox Code Playgroud)

使用示例:

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);
}
Run Code Online (Sandbox Code Playgroud)

笔记:

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


Teo*_*cci 6

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

这里简单解释一下。

错误的代码在此输入图像描述

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);
Run Code Online (Sandbox Code Playgroud)

上面的代码试图捕获source变量上的二进制字符串,但是FileReader.readAsBinaryString()返回undefinedonload这是因为只要事件被触发,结果就可用。正如我们所看到的,他试图获得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) 
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,最后一步是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()
Run Code Online (Sandbox Code Playgroud)

Teo,异步是什么意思?

好吧,年轻的学徒,异步意味着我们不知道结果什么时候会准备好,它在每个系统中可能有所不同,并且取决于过程的繁重或复杂程度,而且它还可以发现一些不会产生任何结果的错误全部。

因此,如果一个进程是异步的,那么使用方法封装它async并返回Promise如下所示是一个很好的做法:

const blobToBase64 = async blob => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => resolve(reader.result)
    reader.onerror = err => reject(err)
    reader.readAsDataURL(blob)
  })
}
Run Code Online (Sandbox Code Playgroud)

啊,好吧,Teo,但是 Promise 是什么?

好问题,我的年轻人。对象Promise表示异步操作的最终完成(或失败)及其结果值。换句话说,将告诉我们结果是否已准备好并为我们提供其值,否则将返回错误。

blobToBase64上面的代码显示了一个将返回 a 的函数Promise,这意味着该函数将reader.result在准备好时返回。

我们如何将它集成到我们的代码中?

超级简单,只需用上面定义的函数替换所有 FileReaderblobToBase64并像这样调用它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.onerror = err => reject(err)
    reader.readAsDataURL(blob)
  })
}

const loadImage = async() => {
  const imageBlob = await fetchImage(url)
  const imageBase64 = await blobToBase64(imageBlob)
  
  console.log({imageBase64})
}

loadImage()
Run Code Online (Sandbox Code Playgroud)


Ali*_*dri 5

您可以通过以下方式解决问题:

var canvas = $('#canvas'); 
var b64Text = canvas.toDataURL();
b64Text = b64Text.replace('data&colon;image/png;base64,','');
var base64Data = b64Text;
Run Code Online (Sandbox Code Playgroud)

我希望这对你有帮助


小智 5

所以问题是你想上传一个 base 64 图像并且你有一个 blob url。现在适用于所有 html 5 浏览器的答案是:做:

  var fileInput = document.getElementById('myFileInputTag');
  var preview = document.getElementById('myImgTag');

  fileInput.addEventListener('change', function (e) {
      var url = URL.createObjectURL(e.target.files[0]);
      preview.setAttribute('src', url);
  });
function Upload()
{
     // preview can be image object or image element
     var myCanvas = document.getElementById('MyCanvas');
     var ctx = myCanvas.getContext('2d');
     ctx.drawImage(preview, 0,0);
     var base64Str = myCanvas.toDataURL();
     $.ajax({
         url: '/PathToServer',
         method: 'POST',
         data: {
             imageString: base64Str
         },
     success: function(data) { if(data && data.Success) {}},
     error: function(a,b,c){alert(c);}
     });
 }
Run Code Online (Sandbox Code Playgroud)


Vit*_*kov 5

另一种方法是使用一个简单的包装器来FileReader返回Observable(代码片段位于TypeScript):

  function toBase64(blob: Blob): Observable<string> {
    const reader = new FileReader();
    reader.readAsDataURL(blob);
    return fromEvent(reader, 'load')
      .pipe(map(() => (reader.result as string).split(',')[1]));
  }
Run Code Online (Sandbox Code Playgroud)

用法:

toBase64(blob).subscribe(base64 => console.log(base64));
Run Code Online (Sandbox Code Playgroud)