来自 DataURL 的 Blob?
Posted
技术标签:
【中文标题】来自 DataURL 的 Blob?【英文标题】:Blob from DataURL? 【发布时间】:2012-08-23 12:44:04 【问题描述】:使用FileReader
的readAsDataURL()
我可以将任意数据转换为数据URL。有没有办法使用内置浏览器 API 将数据 URL 转换回 Blob
实例?
【问题讨论】:
【参考方案1】:使用
FileReader.readAsArrayBuffer(Blob|File)
而不是
FileReader.readAsDataURL(Blob|File)
【讨论】:
我必须将它作为 DataURL 无限期地存储在 localStorage 中,因此使用替代ArrayBuffer
路径将不起作用。【参考方案2】:
用户 Matt 在一年前提出了以下代码 (How to convert dataURL to file object in javascript?),可能会对您有所帮助
编辑:正如一些评论者所报告的,BlobBuilder 已在一段时间前被弃用。这是更新后的代码:
function dataURItoBlob(dataURI)
// convert base64 to raw binary data held in a string
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var byteString = atob(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
// write the bytes of the string to an ArrayBuffer
var ab = new ArrayBuffer(byteString.length);
// create a view into the buffer
var ia = new Uint8Array(ab);
// set the bytes of the buffer to the correct values
for (var i = 0; i < byteString.length; i++)
ia[i] = byteString.charCodeAt(i);
// write the ArrayBuffer to a blob, and you're done
var blob = new Blob([ab], type: mimeString);
return blob;
【讨论】:
重复的拆分似乎有点浪费,因为这可能是一个非常大的字符串。 变量“ia”的作用是什么 - 它分配了一个值,但从未用于形成 blob。为什么? Blaze,Ward:ia 是缓冲区的视图。因此,当您在 ia 中设置每个字节时,它正在写入缓冲区。如果没有 ia 循环,缓冲区将完全为空。 如何找到 SO answer #6850276 ? @BT :我猜***.com/a/30407840/271577 是有意的(注意重定向的 URL 包括“#6850276”)。【参考方案3】:dataURItoBlob : function(dataURI, dataTYPE)
var binary = atob(dataURI.split(',')[1]), array = [];
for(var i = 0; i < binary.length; i++) array.push(binary.charCodeAt(i));
return new Blob([new Uint8Array(array)], type: dataTYPE);
输入dataURI为Data URL,dataTYPE为文件类型,然后输出blob对象
【讨论】:
dataTYPE
嵌入在 dataURI
中,因此应该像第一个答案一样解析。
dataURL2Blob 来自我的图像处理插件,您可以查看此链接。我只是复制我自己的代码。 github.com/xenophon566/html5.upload/blob/master/js/…【参考方案4】:
尝试:
function dataURItoBlob(dataURI)
if(typeof dataURI !== 'string')
throw new Error('Invalid argument: dataURI must be a string');
dataURI = dataURI.split(',');
var type = dataURI[0].split(':')[1].split(';')[0],
byteString = atob(dataURI[1]),
byteStringLength = byteString.length,
arrayBuffer = new ArrayBuffer(byteStringLength),
intArray = new Uint8Array(arrayBuffer);
for (var i = 0; i < byteStringLength; i++)
intArray[i] = byteString.charCodeAt(i);
return new Blob([intArray],
type: type
);
【讨论】:
【参考方案5】:使用我的代码将 dataURI 转换为 blob。 它比其他的更简单、更干净。
function dataURItoBlob(dataURI)
var arr = dataURI.split(','), mime = arr[0].match(/:(.*?);/)[1];
return new Blob([atob(arr[1])], type:mime);
【讨论】:
您能解释一下为什么您的代码不需要转换为 int 数组,而其他人都在这样做吗? 参见 MDN 上的Blob() constructor @Rikard 你是什么意思?它不会影响任何图像 这只适用于一些基本的东西。您需要首先对其进行转义 + decodeURIComponent 以支持大多数内容编码read this。这就是为什么其他人将字符串转换为 int 数组以避免缓慢/饥饿的 decodeURIComponent/atob 函数调用并直接转换为字节【参考方案6】:基于 XHR 的方法。
function dataURLtoBlob( dataUrl, callback )
var req = new XMLHttpRequest;
req.open( 'GET', dataUrl );
req.responseType = 'arraybuffer'; // Can't use blob directly because of https://crbug.com/412752
req.onload = function fileLoaded(e)
// If you require the blob to have correct mime type
var mime = this.getResponseHeader('content-type');
callback( new Blob([this.response], type:mime) );
;
req.send();
dataURLtoBlob( 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg==', function( blob )
console.log( blob );
);
【讨论】:
看来,这是目前最好的办法。谢谢! 无法在 Safari 中工作 - 如果页面从 HTTPS 加载,它将引发跨域错误。 问题是来自DataURL的Blob?【参考方案7】:类似于@Adria 方法,但使用 Fetch api 并且更小 [caniuse?] 不必考虑 mimetype,因为 blob 响应类型开箱即用
警告:可能违反内容安全政策 (CSP) ...如果你使用那些东西
var url = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=="
fetch(url)
.then(res => res.blob())
.then(blob => console.log(blob))
不要认为你可以在不使用 lib 的情况下做得比这更小
【讨论】:
非常优雅。不幸的是,edge 13 和 safari 不支持“获取”。 edge 14 和 safari 10.1 支持 异步版本:const blob = await (await fetch(url)).blob();
效果很好,但是从服务器读取文件时没有扩展名。有什么想法吗?
fetch
的更大问题是它强制使用异步 API。【参考方案8】:
由于这些答案都不支持 base64 和非 base64 数据 URL,因此这是基于 vuamitom 已删除答案的答案:
// from https://***.com/questions/37135417/download-canvas-as-png-in-fabric-js-giving-network-error/
var dataURLtoBlob = exports.dataURLtoBlob = function(dataurl)
var parts = dataurl.split(','), mime = parts[0].match(/:(.*?);/)[1]
if(parts[0].indexOf('base64') !== -1)
var bstr = atob(parts[1]), n = bstr.length, u8arr = new Uint8Array(n)
while(n--)
u8arr[n] = bstr.charCodeAt(n)
return new Blob([u8arr], type:mime)
else
var raw = decodeURIComponent(parts[1])
return new Blob([raw], type: mime)
注意:我不确定是否有可能需要以不同方式处理的 other dataURL mime 类型。但是,如果你发现了,请告诉我!可能 dataURL 可以简单地具有他们想要的任何格式,在这种情况下,您可以为您的特定用例找到正确的代码。
【讨论】:
【参考方案9】:使用XHR API 创建一个blob:
function dataURLtoBlob( dataUrl, callback )
var req = new XMLHttpRequest;
req.open( 'GET', dataUrl );
req.responseType = 'blob';
req.onload = function fileLoaded(e)
callback(this.response);
;
req.send();
var dataURI = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAUAAAAFCAYAAACNbyblAAAAHElEQVQI12P4//8/w38GIAXDIBKE0DHxgljNBAAO9TXL0Y4OHwAAAABJRU5ErkJggg=='
dataURLtoBlob(dataURI , function( blob )
console.log( blob );
);
【讨论】:
Chrome 抛出 net::ERR_INVALID_URL【参考方案10】:在modern browsers 中,可以使用 Christian d'Heureuse 在评论中建议的 one liner:
const blob = await (await fetch(dataURI)).blob();
【讨论】:
使用此方法的一个警告是,如果您的应用程序有任何内容安全策略 (CSP),这可能会违反您的内容安全策略 (CSP)。【参考方案11】:如果您需要在 Google Apps 脚本的服务器端工作,请尝试:
function dataURItoBlob(dataURI)
// convert base64 to Byte[]
// doesn't handle URLEncoded DataURIs - see SO answer #6850276 for code that does this
var data = Utilities.base64Decode(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
var blob = Utilities.newBlob(data);
blob.setContentType(mimeString);
return blob;
【讨论】:
以上是关于来自 DataURL 的 Blob?的主要内容,如果未能解决你的问题,请参考以下文章