【问题标题】:How to convert dataURL to file object in javascript?如何在javascript中将dataURL转换为文件对象?
【发布时间】:2011-10-14 14:00:15
【问题描述】:

我需要将 dataURL 转换为 Javascript 中的 File 对象,以便使用 AJAX 发送它。可能吗?如果是,请告诉我怎么做。

【问题讨论】:

  • cwallenpoole,它是一个大代码,在图像附加到正文之前一切正常,只要告诉我你需要什么,我会在这里发布
  • 您的脚本/页面中的formData 是什么?
  • 由于您使用的是 toDataURL,它会将画布图像作为 b64 编码字符串而不是文件。由于您使用的是“POST”,这就是它存储在 $_POST 中的原因。 “但这将是一个丑陋的黑客”这不是一个丑陋的黑客,而是文件的创建方式。
  • formdata 在包含这两个函数的块中被初始化如下, var formdata = new FormData();

标签: javascript jquery fileapi


【解决方案1】:

从 dataURL 创建 blob:

const blob = await (await fetch(dataURL)).blob(); 

从 blob 创建文件:

const file = new File([blob], 'fileName.jpg', {type:"image/jpeg", lastModified:new Date()});

【讨论】:

  • 非常感谢!这种从 dataURL 创建 blob 的简洁解决方案非常有效:-)
  • 不需要 2 次等待和嵌套。 await fetch(src).then(it => it.blob())
【解决方案2】:

如果你真的想把dataURL转换成File对象。

您需要将dataURL 转换为Blob,然后将Blob 转换为File。 该功能来自马修的回答。 (https://stackoverflow.com/a/7261048/13647044)

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);
      var ia = new Uint8Array(ab);
      for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
      }
      return new Blob([ab], { type: mimeString });
    }

const blob = dataURItoBlob(url);
const resultFile = new File([blob], "file_name");

除此之外,您还可以对 File 对象进行初始化。 Reference 到 File() 构造函数。

const resultFile = new File([blob], "file_name",{type:file.type,lastModified:1597081051454});

类型应为[MIME][1] 类型(即image/jpeg),在我的示例中最后修改的值等于Mon Aug 10 2020 19:37:31 GMT+0200 (Eastern European Standard Time)

【讨论】:

    【解决方案3】:

    如果您需要通过 ajax 发送,则无需使用 File 对象,只需要 BlobFormData 对象。

    正如我的旁注,您为什么不直接通过 ajax 将 base64 字符串发送到服务器并将其转换为二进制服务器端,例如使用 PHP 的 base64_decode?无论如何,来自this answer 的符合标准的代码适用于 Chrome 13 和 WebKit nightlies:

    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);
        var ia = new Uint8Array(ab);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
    
        //Old Code
        //write the ArrayBuffer to a blob, and you're done
        //var bb = new BlobBuilder();
        //bb.append(ab);
        //return bb.getBlob(mimeString);
    
        //New Code
        return new Blob([ab], {type: mimeString});
    
    
    }
    

    然后只需将 blob 附加到新的 FormData 对象并使用 ajax 将其发布到您的服务器:

    var blob = dataURItoBlob(someDataUrl);
    var fd = new FormData(document.forms[0]);
    var xhr = new XMLHttpRequest();
    
    fd.append("myFile", blob);
    xhr.open('POST', '/', true);
    xhr.send(fd);
    

    【讨论】:

    • 感谢您的回答,但是,我已经制作了类似的东西并且效果很好。它是一个基于画布的图像缩放器、水印器和上传器。等待项目使用它
    • 嗨,我想提一下我在nixtu.info/2013/06/how-to-upload-canvas-data-to-server.html 有一个稍微现代化的版本。
    • BlobBuilder 现已弃用,在 Chrome 中不再工作!
    • 这篇文章使用了已弃用的元素,例如 BlobBuilder,请参阅@cuixiping 的答案以获得有效的解决方案。
    • 值得注意的是,文件的base64编码通常比实际文件大得多,这意味着与multipart/form-data相比,使用base64传输的数据要多得多,这就是你得到的当你使用File时。
    【解决方案4】:

    经过一番研究,我找到了这个:

    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);
        var dw = new DataView(ab);
        for(var i = 0; i < byteString.length; i++) {
            dw.setUint8(i, byteString.charCodeAt(i));
        }
        // write the ArrayBuffer to a blob, and you're done
        return new Blob([ab], {type: mimeString});
    }
    
    module.exports = dataURItoBlob;

    【讨论】:

      【解决方案5】:

      BlobBuilder 已弃用,不应再使用。使用 Blob 而不是旧的 BlobBuilder。代码非常干净简洁。

      文件对象继承自 Blob 对象。您可以将它们与 FormData 对象一起使用。

      function dataURLtoBlob(dataurl) {
          var arr = dataurl.split(','), mime = arr[0].match(/:(.*?);/)[1],
              bstr = atob(arr[1]), n = bstr.length, u8arr = new Uint8Array(n);
          while(n--){
              u8arr[n] = bstr.charCodeAt(n);
          }
          return new Blob([u8arr], {type:mime});
      }
      

      使用 dataURLtoBlob() 函数将 dataURL 转换为 blob 并将 ajax 发送到服务器。

      例如:

      var dataurl = 'data:text/plain;base64,aGVsbG8gd29ybGQ=';
      var blob = dataURLtoBlob(dataurl);
      var fd = new FormData();
      fd.append("file", blob, "hello.txt");
      var xhr = new XMLHttpRequest();
      xhr.open('POST', '/server.php', true);
      xhr.onload = function(){
          alert('upload complete');
      };
      xhr.send(fd);
      

      另一种方式:

      您也可以使用fetch 将url 转换为文件对象(文件对象具有name/fileName 属性,这与blob 对象不同)

      代码非常简短且易于使用。 (works in Chrome and Firefox)

      //load src and convert to a File instance object
      //work for any type of src, not only image src.
      //return a promise that resolves with a File instance
      
      function srcToFile(src, fileName, mimeType){
          return (fetch(src)
              .then(function(res){return res.arrayBuffer();})
              .then(function(buf){return new File([buf], fileName, {type:mimeType});})
          );
      }
      

      使用示例1:只需转换为文件对象

      srcToFile(
          'data:text/plain;base64,aGVsbG8gd29ybGQ=',
          'hello.txt',
          'text/plain'
      )
      .then(function(file){
          console.log(file);
      })
      

      使用示例2:转换为文件对象并上传到服务器

      srcToFile(
          'data:text/plain;base64,aGVsbG8gd29ybGQ=',
          'hello.txt',
          'text/plain'
      )
      .then(function(file){
          console.log(file);
          var fd = new FormData();
          fd.append("file", file);
          return fetch('/server.php', {method:'POST', body:fd});
      })
      .then(function(res){
          return res.text();
      })
      .then(console.log)
      .catch(console.error)
      ;
      

      【讨论】:

      • 我真的很喜欢你的回答,因为它干净整洁,但我真的可以弄清楚 ArrayBuffer 在其他答案中的用法。请您解释一下 ArrayBuffer 的用法以及这里为什么不使用它?
      • 喜欢它!最佳答案 imo
      • 如果您没有查看 Mozilla Developer Network 参考资料,则 fetch 是一项实验性功能,不建议在生产代码中使用。太糟糕了,看起来很酷。
      • 没有promise版本会怎样?
      猜你喜欢
      • 1970-01-01
      • 2020-11-12
      • 2018-09-12
      • 2017-04-13
      • 2020-02-21
      • 1970-01-01
      • 1970-01-01
      • 2014-10-30
      • 1970-01-01
      相关资源
      最近更新 更多