将blob转换为base64

这是我想要执行BlobBase64 string的代码片段:

这个注释部分可以工作,当它生成的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文件如在上面的代码?

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

形成文档 readAsDataURL编码到base64

作为awaitable函数:

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);
};

你可以通过以下方法解决问题:

var canvas = $('#canvas');
var b64Text = canvas.toDataURL();
b64Text = b64Text.replace('data:image/png;base64,','');
var base64Data = b64Text;

我希望这对你有帮助

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);
}
所以问题是你想上传一张64进制的图片,你有一个blob url。现在的答案,将工作在所有html 5浏览器是: 做的事:< / p >
  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);}
});
}
function bufferToBinaryString(arrayBuffer){
return String.fromCharCode(...new Uint8Array(arrayBuffer));
}
(async () => console.log(btoa(bufferToBinaryString(await new Response(blob).arrayBuffer()))))();

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

参见响应的构造函数,你可以将[blob, buffer source form data, readable stream, etc.]转换为响应,然后通过async方法/回调将其转换为[json, text, array buffer, blob]

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

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

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

为了使用这个helper函数,你应该设置一个回调函数,例如:

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

我在React Native项目上为我的问题写了这个helper函数,我想下载一张图像,然后将它存储为缓存图像:

fetch(imageAddressAsStringValue)
.then(res => res.blob())
.then(blobToBase64)
.then(finalResult => {
storeOnMyLocalDatabase(finalResult);
});

我想要的东西,我可以访问base64值存储到一个列表,为我添加事件监听器工作。您只需要FileReader,它将读取图像blob并在结果中返回base64。

createImageFromBlob(image: Blob) {
const reader = new FileReader();
const supportedImages = []; // you can also refer to some global variable
reader.addEventListener(
'load',
() => {
// reader.result will have the required base64 image
const base64data = reader.result;
supportedImages.push(base64data); // this can be a reference to global variable and store the value into that global list so as to use it in the other part
},
false
);
// The readAsDataURL method is used to read the contents of the specified Blob or File.
if (image) {
reader.readAsDataURL(image);
}
}

最后一部分是readAsDataURL,它非常重要,用于读取指定Blob的内容

另一种方法是使用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]));
}

用法:

toBase64(blob).subscribe(base64 => console.log(base64));
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));

参见:

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

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))

也许我遗漏了什么,但是

let encoded = btoa(await myblob.text());

... 是将Blob的数据编码为base64所需要做的全部工作。参见Blob.text()btoa()

或者如果你想把所有事情都当做承诺

let encode = myblob.text().then(btoa);

PS:解码回一个Blob: new Blob([atob(encoded)])

如果你的"blob"是一个实际的Blob Object而不是blob url,转换非常简单:

const reader = new FileReader()
reader.readAsDataURL(blob)
reader.onload = () => resolve(reader.result)

Blob Object的例子:

console.log(blob)

输出:

Blob {lastModified: 1658039931443, lastModifiedDate: Sun Jul 17 2022 08:38:51 GMT+0200 (Central European Summer Time), name: '1.jpg', size: 35493, type: 'image/jpeg'}
lastModified: 1658039931443
lastModifiedDate: Sun Jul 17 2022 08:38:51 GMT+0200 (Central European Summer Time) {}
name: "1.jpg"
size: 35493
type: "image/jpeg"
[[Prototype]]: Blob

在我的例子中,blob是由Compressorjs产生的(如果你需要图像压缩)。

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

这里有一个简单的解释。

错误代码enter image description here

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);

上面的代码试图捕获source变量的二进制字符串,然而,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.result

如何将其集成到代码中?

超级简单,只需将所有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()