来自 DataURL 的 Blob?

Posted

技术标签:

【中文标题】来自 DataURL 的 Blob?【英文标题】:Blob from DataURL? 【发布时间】:2012-08-23 12:44:04 【问题描述】:

使用FileReaderreadAsDataURL() 我可以将任意数据转换为数据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?的主要内容,如果未能解决你的问题,请参考以下文章

Canvas转换为Blob对象并使用Ajax发送

如何在 JavaScript 中将 Blob 转换为文件

Base64转Blob的方式

base64blob格式相互转换及应用

base64blob格式相互转换及应用

base64blob格式相互转换及应用