405 javascript base64
我在字符串中有base64编码的二进制数据.
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
Run Code Online (Sandbox Code Playgroud)
我想创建一个blob:
包含此数据的URL并将其显示给用户.
const blob = new Blob(????, {type: contentType});
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Run Code Online (Sandbox Code Playgroud)
我还没有弄清楚如何创建Blob
.
在某些情况下,我可以通过使用data:
URL 来避免这种情况.
const dataUrl = `data:${contentType};base64,${b64Data}`;
window.location = dataUrl;
Run Code Online (Sandbox Code Playgroud)
但是在大多数情况下,data:
URL非常大.
如何Blob
在JavaScript中将base64字符串解码为对象?
小智 724
NPM上提供了下述功能:
atob
该.charCodeAt
函数将base64编码的字符串解码为一个新字符串,其中包含二进制数据每个字节的字符.
const byteCharacters = atob(b64Data);
Run Code Online (Sandbox Code Playgroud)
每个字符的代码点(charCode)都是字节的值.我们可以通过使用Uint8Array
字符串中每个字符的方法应用它来创建一个字节值数组.
const byteNumbers = new Array(byteCharacters.length);
for (let i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
Run Code Online (Sandbox Code Playgroud)
您可以将此字节值数组转换为实际类型的字节数组,方法是将其传递给Blob
构造函数.
const byteArray = new Uint8Array(byteNumbers);
Run Code Online (Sandbox Code Playgroud)
这反过来可以Blob
通过将其包装在一个将其传递给byteCharacters
构造函数的数组中转换为a .
const blob = new Blob([byteArray], {type: contentType});
Run Code Online (Sandbox Code Playgroud)
上面的代码有效.然而,通过处理atob
较小的切片而不是一次性处理,可以稍微改善性能.在我的粗略测试中,512字节似乎是一个很好的切片大小.这给了我们以下功能.
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
Run Code Online (Sandbox Code Playgroud)
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
window.location = blobUrl;
Run Code Online (Sandbox Code Playgroud)
const b64toBlob = (b64Data, contentType='', sliceSize=512) => {
const byteCharacters = atob(b64Data);
const byteArrays = [];
for (let offset = 0; offset < byteCharacters.length; offset += sliceSize) {
const slice = byteCharacters.slice(offset, offset + sliceSize);
const byteNumbers = new Array(slice.length);
for (let i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
const byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
const blob = new Blob(byteArrays, {type: contentType});
return blob;
}
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = b64toBlob(b64Data, contentType);
const blobUrl = URL.createObjectURL(blob);
const img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
Run Code Online (Sandbox Code Playgroud)
const byteCharacters = atob(b64Data);
Run Code Online (Sandbox Code Playgroud)
End*_*ess 221
无法避免在没有依赖项或库的情况下发布简约方法.
它需要新的fetch API.我可以用吗?
var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
fetch(url)
.then(res => res.blob())
.then(console.log)
Run Code Online (Sandbox Code Playgroud)
使用此方法,您还可以轻松获取arraybuffer,text和json
我对Jeremy的es6同步版进行了简单的性能测试.
同步版本将阻止UI一段时间.
const b64toBlob = (base64, type = 'application/octet-stream') =>
fetch(`data:${type};base64,${base64}`).then(res => res.blob())
Run Code Online (Sandbox Code Playgroud)
Bac*_*her 67
优化(但不太可读)的实现:
function base64toBlob(base64Data, contentType) {
contentType = contentType || '';
var sliceSize = 1024;
var byteCharacters = atob(base64Data);
var bytesLength = byteCharacters.length;
var slicesCount = Math.ceil(bytesLength / sliceSize);
var byteArrays = new Array(slicesCount);
for (var sliceIndex = 0; sliceIndex < slicesCount; ++sliceIndex) {
var begin = sliceIndex * sliceSize;
var end = Math.min(begin + sliceSize, bytesLength);
var bytes = new Array(end - begin);
for (var offset = begin, i = 0; offset < end; ++i, ++offset) {
bytes[i] = byteCharacters[offset].charCodeAt(0);
}
byteArrays[sliceIndex] = new Uint8Array(bytes);
}
return new Blob(byteArrays, { type: contentType });
}
Run Code Online (Sandbox Code Playgroud)
小智 19
以下是我的 TypeScript 代码,它可以轻松转换为 JavaScript,您可以使用
/**
* Convert BASE64 to BLOB
* @param base64Image Pass Base64 image data to convert into the BLOB
*/
private convertBase64ToBlob(base64Image: string) {
// Split into two parts
const parts = base64Image.split(';base64,');
// Hold the content type
const imageType = parts[0].split(':')[1];
// Decode Base64 string
const decodedData = window.atob(parts[1]);
// Create UNIT8ARRAY of size same as row data length
const uInt8Array = new Uint8Array(decodedData.length);
// Insert all character code into uInt8Array
for (let i = 0; i < decodedData.length; ++i) {
uInt8Array[i] = decodedData.charCodeAt(i);
}
// Return BLOB image after conversion
return new Blob([uInt8Array], { type: imageType });
}
Run Code Online (Sandbox Code Playgroud)
Jay*_*Lin 18
对于所有浏览器支持,特别是在Android上.也许你可以添加这个
try{
blob = new Blob( byteArrays, {type : contentType});
}
catch(e){
// TypeError old chrome and FF
window.BlobBuilder = window.BlobBuilder ||
window.WebKitBlobBuilder ||
window.MozBlobBuilder ||
window.MSBlobBuilder;
if(e.name == 'TypeError' && window.BlobBuilder){
var bb = new BlobBuilder();
bb.append(byteArrays);
blob = bb.getBlob(contentType);
}
else if(e.name == "InvalidStateError"){
// InvalidStateError (tested on FF13 WinXP)
blob = new Blob(byteArrays, {type : contentType});
}
else{
// We're screwed, blob constructor unsupported entirely
}
}
Run Code Online (Sandbox Code Playgroud)
小智 16
对于像我一样的所有复制粘贴爱好者,这里有一个适用于 Chrome、Firefox 和 Edge 的熟下载功能:
window.saveFile = function (bytesBase64, mimeType, fileName) {
var fileUrl = "data:" + mimeType + ";base64," + bytesBase64;
fetch(fileUrl)
.then(response => response.blob())
.then(blob => {
var link = window.document.createElement("a");
link.href = window.URL.createObjectURL(blob, { type: mimeType });
link.download = fileName;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
});
}
Run Code Online (Sandbox Code Playgroud)
ami*_*sim 13
对于图像数据,我觉得使用起来比较简单canvas.toBlob
(异步)
function b64toBlob(b64, onsuccess, onerror) {
var img = new Image();
img.onerror = onerror;
img.onload = function onload() {
var canvas = document.createElement('canvas');
canvas.width = img.width;
canvas.height = img.height;
var ctx = canvas.getContext('2d');
ctx.drawImage(img, 0, 0, canvas.width, canvas.height);
canvas.toBlob(onsuccess);
};
img.src = b64;
}
var base64Data = 'data:image/jpg;base64,/9j/4AAQSkZJRgABAQA...';
b64toBlob(base64Data,
function(blob) {
var url = window.URL.createObjectURL(blob);
// do something with url
}, function(error) {
// handle error
});
Run Code Online (Sandbox Code Playgroud)
Pap*_*api 13
我发布了一种更具声明性的同步 Base64 转换方式。虽然 asyncfetch().blob()
非常简洁而且我非常喜欢这个解决方案,但它在 Internet Explorer 11(可能还有 Edge - 我没有测试过这个)上不起作用,即使使用 polyfill - 看看我对Endless 的评论发帖了解更多详情。
const blobPdfFromBase64String = base64String => {
const byteArray = Uint8Array.from(
atob(base64String)
.split('')
.map(char => char.charCodeAt(0))
);
return new Blob([byteArray], { type: 'application/pdf' });
};
Run Code Online (Sandbox Code Playgroud)
如果您想打印它,您可以执行以下操作:
const isIE11 = !!(window.navigator && window.navigator.msSaveOrOpenBlob); // Or however you want to check it
const printPDF = blob => {
try {
isIE11
? window.navigator.msSaveOrOpenBlob(blob, 'documents.pdf')
: printJS(URL.createObjectURL(blob)); // http://printjs.crabbly.com/
} catch (e) {
throw PDFError;
}
};
Run Code Online (Sandbox Code Playgroud)
如果您能够在服务器上对 Base64 字符串进行一些预处理,则可以在某个 URL 下公开它并使用printJS
:) 中的链接
Arc*_*ela 12
看到这个例子:https://jsfiddle.net/pqhdce2L/
function b64toBlob(b64Data, contentType, sliceSize) {
contentType = contentType || '';
sliceSize = sliceSize || 512;
var byteCharacters = atob(b64Data);
var byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
var slice = byteCharacters.slice(offset, offset + sliceSize);
var byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
var byteArray = new Uint8Array(byteNumbers);
byteArrays.push(byteArray);
}
var blob = new Blob(byteArrays, {type: contentType});
return blob;
}
var contentType = 'image/png';
var b64Data = Your Base64 encode;
var blob = b64toBlob(b64Data, contentType);
var blobUrl = URL.createObjectURL(blob);
var img = document.createElement('img');
img.src = blobUrl;
document.body.appendChild(img);
Run Code Online (Sandbox Code Playgroud)
我注意到,在切换像jeremy建议的数据时,Internet Explorer 11变得异常缓慢.这适用于Chrome,但在将切片数据传递给Blob-Constructor时IE似乎有问题.在我的机器上,传递5 MB的数据会导致IE崩溃和内存消耗.Chrome会立即创建blob.
运行此代码以进行比较:
var byteArrays = [],
megaBytes = 2,
byteArray = new Uint8Array(megaBytes*1024*1024),
block,
blobSlowOnIE, blobFastOnIE,
i;
for (i = 0; i < (megaBytes*1024); i++) {
block = new Uint8Array(1024);
byteArrays.push(block);
}
//debugger;
console.profile("No Slices");
blobSlowOnIE = new Blob(byteArrays, { type: 'text/plain' });
console.profileEnd();
console.profile("Slices");
blobFastOnIE = new Blob([byteArray], { type: 'text/plain' });
console.profileEnd();
Run Code Online (Sandbox Code Playgroud)
所以我决定在一个函数中包含jeremy描述的两种方法.积分是为了这个.
function base64toBlob(base64Data, contentType, sliceSize) {
var byteCharacters,
byteArray,
byteNumbers,
blobData,
blob;
contentType = contentType || '';
byteCharacters = atob(base64Data);
// Get blob data sliced or not
blobData = sliceSize ? getBlobDataSliced() : getBlobDataAtOnce();
blob = new Blob(blobData, { type: contentType });
return blob;
/*
* Get blob data in one slice.
* => Fast in IE on new Blob(...)
*/
function getBlobDataAtOnce() {
byteNumbers = new Array(byteCharacters.length);
for (var i = 0; i < byteCharacters.length; i++) {
byteNumbers[i] = byteCharacters.charCodeAt(i);
}
byteArray = new Uint8Array(byteNumbers);
return [byteArray];
}
/*
* Get blob data in multiple slices.
* => Slow in IE on new Blob(...)
*/
function getBlobDataSliced() {
var slice,
byteArrays = [];
for (var offset = 0; offset < byteCharacters.length; offset += sliceSize) {
slice = byteCharacters.slice(offset, offset + sliceSize);
byteNumbers = new Array(slice.length);
for (var i = 0; i < slice.length; i++) {
byteNumbers[i] = slice.charCodeAt(i);
}
byteArray = new Uint8Array(byteNumbers);
// Add slice
byteArrays.push(byteArray);
}
return byteArrays;
}
}
Run Code Online (Sandbox Code Playgroud)
只需在浏览器中
Uint8Array.from(atob(YOUR_BASE64_DATA), (c) => c.charCodeAt(0))
Run Code Online (Sandbox Code Playgroud)
与之比较fetch
!(async () => {
const start = performance.now();
let i = 0;
while (i++ < 1e3) {
const dataUrl =
"data:application/octet-stream;base64,H4sIAAAAAAAAA0vOzyvOz0nVy8lP10jISM3JyVdIr8osUFCpdkksSdXLyy/X0KxN0ORKHlU3qm5U3ai6UXWj6kauOgBVt1KRLwcAAA==";
body = await (await fetch(dataUrl)).blob();
}
console.log(performance.now() - start); // 508.19999999925494ms
})();
Run Code Online (Sandbox Code Playgroud)
!(async () => {
const start = performance.now();
let i = 0;
while (i++ < 1e3) {
const base64Data =
"H4sIAAAAAAAAA0vOzyvOz0nVy8lP10jISM3JyVdIr8osUFCpdkksSdXLyy/X0KxN0ORKHlU3qm5U3ai6UXWj6kauOgBVt1KRLwcAAA==";
body = Uint8Array.from(atob(base64Data), (c) => c.charCodeAt(0));
}
console.log(performance.now() - start); // 7.899999998509884ms
})();
Run Code Online (Sandbox Code Playgroud)
根据您的数据大小,选择性能一。
如果你能忍受向你的项目添加一个依赖项,那么伟大的blob-util
npm 包提供了一个方便的base64StringToBlob
功能。添加到您的后,package.json
您可以像这样使用它:
import { base64StringToBlob } from 'blob-util';
const contentType = 'image/png';
const b64Data = 'iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==';
const blob = base64StringToBlob(b64Data, contentType);
// Do whatever you need with your blob...
Run Code Online (Sandbox Code Playgroud)
带 fetch 的方法是最好的解决方案,但如果有人需要使用不带 fetch 的方法,那么就在这里,因为前面提到的方法对我不起作用:
function makeblob(dataURL) {
const BASE64_MARKER = ';base64,';
const parts = dataURL.split(BASE64_MARKER);
const contentType = parts[0].split(':')[1];
const raw = window.atob(parts[1]);
const rawLength = raw.length;
const uInt8Array = new Uint8Array(rawLength);
for (let i = 0; i < rawLength; ++i) {
uInt8Array[i] = raw.charCodeAt(i);
}
return new Blob([uInt8Array], { type: contentType });
}
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
394661 次 |
最近记录: |