【问题标题】:Convert URL to File or Blob for FileReader.readAsDataURL将 URL 转换为 FileReader.readAsDataURL 的文件或 Blob
【发布时间】:2014-07-30 20:27:36
【问题描述】:

参考:FileReader.readAsDataURL

考虑以下示例:

function previewFile(file) {

  var reader  = new FileReader();

  reader.onloadend = function () {
    console.log(reader.result);
  }
  reader.readAsDataURL(file);
}

它说:

instanceOfFileReader.readAsDataURL(blob);

blob:要从中读取的 Blob 或文件。

  1. 本地文件 URL 像:'file:///C:/path-to/root.png' 传递给readAsDataURL()

  2. FileReader() 在 Firefox 插件中可用吗?

【问题讨论】:

    标签: javascript firefox-addon firefox-addon-restartless


    【解决方案1】:

    要将 URL 转换为 FileReader.readAsDataURL() 的 Blob,请执行以下操作:

    var request = new XMLHttpRequest();
    request.open('GET', MY_URL, true);
    request.responseType = 'blob';
    request.onload = function() {
        var reader = new FileReader();
        reader.readAsDataURL(request.response);
        reader.onload =  function(e){
            console.log('DataURL:', e.target.result);
        };
    };
    request.send();
    

    【讨论】:

    • 这确实可以从一些精心设计中受益,从未在 sn-p 中定义 request.response。可以在已经加载的 url 上使用 responseType 或 FileReader,而无需创建新的 XMLHttpRequest();每次?
    • 这对我有用。使用 DataURL 从 s3 存储桶中的图像加载 paperjs 中的光栅。
    • 它似乎只适用于小文件。如果有800M左右的大mp4大小,浏览器响应和播放需要很长时间。我们如何在这里利用部分响应?
    【解决方案2】:

    扩展 Felix Turner 的响应,这是我将如何将这种方法与 fetch API 一起使用。

    async function createFile(){
      let response = await fetch('http://127.0.0.1:8080/test.jpg');
      let data = await response.blob();
      let metadata = {
        type: 'image/jpeg'
      };
      let file = new File([data], "test.jpg", metadata);
      // ... do something with the file or return it
    }
    createFile();
    

    【讨论】:

    • 我正在尝试这段代码几个小时,但效果不佳。我们需要将contentType 更改为type。谢谢你。上帝保佑你!
    • 是的,这是正确的!我已经进行了编辑。这里也是文档的链接developer.mozilla.org/en-US/docs/Web/API/File/File
    • 如果您不知道文件扩展名或内容类型怎么办?有没有办法从响应获取中提取它?
    • @CMCDragonkai 你可以使用npmjs.com/package/mime-types(增加了几百KB,但我没有找到更简单的方法)
    • 此方法返回 CORS 错误。这是我的question
    【解决方案3】:

    对于 @tibor-udvari 出色的 fetch 答案,建议的编辑队列已满,所以我会将我的建议编辑作为新答案发布。

    如果返回,此函数从标头中获取内容类型,否则回退到可设置的默认类型。

    async function getFileFromUrl(url, name, defaultType = 'image/jpeg'){
      const response = await fetch(url);
      const data = await response.blob();
      return new File([data], name, {
        type: data.type || defaultType,
      });
    }
    
    // `await` can only be used in an async body, but showing it here for simplicity.
    const file = await getFileFromUrl('https://example.com/image.jpg', 'example.jpg');
    

    【讨论】:

      【解决方案4】:

      试试这个我在转换为 ico 时从 @nmaier 那里学到的: 好吧,我真的不明白数组缓冲区是什么,但它可以满足我们的需要:

      function previewFile(file) {
      
        var reader  = new FileReader();
      
        reader.onloadend = function () {
          console.log(reader.result); //this is an ArrayBuffer
        }
        reader.readAsArrayBuffer(file);
      }
      

      请注意我刚刚将您的 readAsDataURL 更改为 readAsArrayBuffer

      这是@nmaier 给我的例子: https://stackoverflow.com/a/24253997/1828637

      它有一个小提琴

      如果你想用它制作一个文件,我想你会在onloadend中使用文件输出流

      【讨论】:

      • 感谢 Noitidart。目前,我正专注于将其转换为 DataURL 我已经测试了其他选项,但到目前为止,上面的代码(如果我让它工作的话)似乎是最干净的 :)
      • 您能否在 gist.github.com 上为您的最终代码提供一个要点并分享,我想看看它是如何完成的 :(
      • 这是给iGoogle的,它将在下一次更新中。
      • @Noitidart 这里到底发生了什么?我们还没有将文件传递给new FileReader 那么它是如何读取的? readAsArraysBufferreader.onload 之前被调用?
      • 嗨@piechuckerr - 现在我非常了解 ArrayBuffers 和 DOMFile 等。上面发生的事情是我们正在传递一个 DOMFile,它正在变成一个 ArrayBuffer。您不能将任何其他内容传递给我在上面发布的此功能。你想做什么?加载本地文件?您可以在插件范围内执行此操作,在非插件范围内,您必须为用户提供 <input type=browse 并让他们浏览到它。 When the pick it, then it will return a DOMFile which you can pass above.或者,如果您的图像位于 http....,一个 sin 遥控器,只需将其与 responseType:arraybuffer 一起 xhr。
      【解决方案5】:

      此信息目前已过时,但无法删除。

      1. 当您的代码具有 chrome 权限时,您只需指定路径即可创建 File instances

        new File("/path/to/file");
        

        FileBlob 的子类,因此所有File 实例也是有效的Blobs。 请注意,这需要a platform path, and not a file URL

      2. 是的,FileReader 可用于插件。

      FileFileReader 在所有windows 中都可用。如果您想在非窗口范围内使用它们(如bootstrap.js 或代码模块),您可以使用nsIDOMFile/nsIDOMFileReader

      【讨论】:

      • 不,不是。为此,您可以使用XHR 来读取(例如,读入数组缓冲区或直接作为文本),然后使用生成的 ArrayBuffer 或文本,或者如果出于某种原因需要 blob,则只需重新包装;)
      • 我将如何从本地文件 URL(而不是路径)执行此操作,例如:file:///storage/emulated/0/Android/data/xxx/cache/1445607245908.jpg
      • 根据developer.mozilla.org/en-US/docs/Web/API/File/File,没有任何File() ctor 仅采用路径。
      • 确实没有那么简单,因为 File(path) 不存在,它不只接受 'path' 作为参数。它应该是这样的:File(bits, path)
      • 使用 fetch api:new File([await (await fetch('/path/to/file')).blob()], '/path/to/file')
      【解决方案6】:

      这是我使用异步等待和承诺的代码

      const getBlobFromUrl = (myImageUrl) => {
          return new Promise((resolve, reject) => {
              let request = new XMLHttpRequest();
              request.open('GET', myImageUrl, true);
              request.responseType = 'blob';
              request.onload = () => {
                  resolve(request.response);
              };
              request.onerror = reject;
              request.send();
          })
      }
      
      const getDataFromBlob = (myBlob) => {
          return new Promise((resolve, reject) => {
              let reader = new FileReader();
              reader.onload = () => {
                  resolve(reader.result);
              };
              reader.onerror = reject;
              reader.readAsDataURL(myBlob);
          })
      }
      
      const convertUrlToImageData = async (myImageUrl) => {
          try {
              let myBlob = await getBlobFromUrl(myImageUrl);
              console.log(myBlob)
              let myImageData = await getDataFromBlob(myBlob);
              console.log(myImageData)
              return myImageData;
          } catch (err) {
              console.log(err);
              return null;
          }
      }
      
      export default convertUrlToImageData;
      

      【讨论】:

      • 这个答案实际上将原始图像返回到单个字节,而不是 看起来 相同的不同图像。如果您正在尝试实现真正想要原始未更改图像的功能,这是最好的答案。谢谢:)
      【解决方案7】:

      我知道这是对@tibor-udvari 答案的扩展,但是为了更好地复制和粘贴。

      async function createFile(url, type){
        if (typeof window === 'undefined') return // make sure we are in the browser
        const response = await fetch(url)
        const data = await response.blob()
        const metadata = {
          type: type || 'video/quicktime'
        }
        return new File([data], url, metadata)
      }
      

      【讨论】:

        【解决方案8】:

        这是使用 vanila.js 和 promise 获取 blob 或文件对象的最简单方法

        const fileURL_to_blob = (file_url) => {
          return new Promise((resolve, reject) => {
            let request = new XMLHttpRequest();
            request.open('GET', file_url, true);
            request.responseType = 'blob';
            request.onload = function() {
                var reader = new FileReader();
                reader.readAsDataURL(request.response);
                reader.onload =  function(e){
                    //console.log('DataURL:', e.target.result);
                    resolve(e.target.result);
                };
            };
            request.onerror=function(e){
              reject(e);
            }
            request.send();
          });
        }
        

        【讨论】:

          猜你喜欢
          • 2017-01-05
          • 2019-10-27
          • 2015-02-17
          • 2016-06-24
          • 2021-12-02
          • 2020-04-15
          • 2020-04-22
          • 1970-01-01
          相关资源
          最近更新 更多