2012-08-09 103 views
76

我允许用户通过拖放和其他方法将图像加载到页面中。当图像丢失时,我使用URL.createObjectURL转换为对象URL以显示图像。我不撤销网址,因为我重复使用它。如何从对象URL获取文件或blob?

所以,当谈到时间来创建一个FormData对象,所以我可以让他们上传的形式,在它的形象之一,是有一些方法,然后我可以扭转这一目标URL回一个BlobFile所以然后我可以将它附加到一个FormData对象?

+0

对前两条评论不感兴趣 - 你需要做的就是发送一个XMLHttpRequest到blob URL。 – gengkev 2012-08-09 03:39:17

+7

多么真棒的问题! – 2013-06-14 20:25:22

+0

为什么不简单地将原始文件对象存储在某个地方,然后使用对象URL来显示它们并在表单上提交使用原始文件? – user764754 2017-01-17 19:12:46

回答

52

至于gengkev暗示在上面他的评论,它看起来像最好的/只有这样,才能做到这一点是一个异步XHR2电话:

var xhr = new XMLHttpRequest(); 
xhr.open('GET', 'blob:http%3A//your.blob.url.here', true); 
xhr.responseType = 'blob'; 
xhr.onload = function(e) { 
    if (this.status == 200) { 
    var myBlob = this.response; 
    // myBlob is now the blob that the object URL pointed to. 
    } 
}; 
xhr.send(); 
+14

在跨域请求的情况下它不起作用。 – 2013-08-20 10:39:31

+14

你什么时候会有一个* objectURL *,它对当前的域和范围来说不是本地的? – BrianFreud 2014-10-04 17:13:27

+4

我做了和上面一样的,但在xhr没有找到404。这是怎么回事? – 2015-01-21 15:20:03

2

如果显示在画布文件,反正你也可以将画布内容转换为Blob对象。

canvas.toBlob(function(my_file){ 
    //.toBlob is only implemented in > FF18 but there is a polyfill 
    //for other browsers https://github.com/blueimp/JavaScript-Canvas-to-Blob 
    var myBlob = (my_file); 
}) 
+1

请注意,这实际上并没有给您返回*相同*原始文件;它正在制作一个新的图像文件。当我上次测试几年前时,我发现至少在Chrome中,新图像文件根本没有压缩 - 我有10k jpgs变成2.5 mb jpgs。 – BrianFreud 2016-06-24 17:09:38

0

不幸的是@ BrianFreud的答案不适合我的需要,我有一点点不同的需求,而且我知道这不是BrianFreud问题的答案,但我要离开这里,因为很多人都以同样的需求来到这里。我需要类似'如何从URL获取文件或blob?',并且当前的正确答案不符合我的需求,因为它不是跨域的。

我有一个网站,从亚马逊的S3/Azure存储消耗的图像,并有我存储与uniqueidentifiers命名对象:

样本:HTTP://****.blob.core.windows。 net/systemimages/bf142dc9-0185-4aee-a3f4-1e5e95a09bcf

某些图像应该从我们的系统界面下载。 为了避免通过我的HTTP服务器传递这个流量,由于这个对象不需要访问任何安全性(除了域过滤),我决定直接请求用户的浏览器并使用本地处理为文件提供一个真实的名称和扩展。

为了实现这个目标我已经使用亨利阿尔伽斯这篇大文章: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/

1.第一步:jQuery的加入二进制支持

/** 
* 
* jquery.binarytransport.js 
* 
* @description. jQuery ajax transport for making binary data type requests. 
* @version 1.0 
* @author Henry Algus <[email protected]mail.com> 
* 
*/ 

// use this transport for "binary" data type 
$.ajaxTransport("+binary", function (options, originalOptions, jqXHR) { 
    // check for conditions and support for blob/arraybuffer response type 
    if (window.FormData && ((options.dataType && (options.dataType == 'binary')) || (options.data && ((window.ArrayBuffer && options.data instanceof ArrayBuffer) || (window.Blob && options.data instanceof Blob))))) { 
     return { 
      // create new XMLHttpRequest 
      send: function (headers, callback) { 
       // setup all variables 
       var xhr = new XMLHttpRequest(), 
     url = options.url, 
     type = options.type, 
     async = options.async || true, 
     // blob or arraybuffer. Default is blob 
     dataType = options.responseType || "blob", 
     data = options.data || null, 
     username = options.username || null, 
     password = options.password || null; 

       xhr.addEventListener('load', function() { 
        var data = {}; 
        data[options.dataType] = xhr.response; 
        // make callback and send data 
        callback(xhr.status, xhr.statusText, data, xhr.getAllResponseHeaders()); 
       }); 

       xhr.open(type, url, async, username, password); 

       // setup custom headers 
       for (var i in headers) { 
        xhr.setRequestHeader(i, headers[i]); 
       } 

       xhr.responseType = dataType; 
       xhr.send(data); 
      }, 
      abort: function() { 
       jqXHR.abort(); 
      } 
     }; 
    } 
}); 

2.第二步:制作请求使用此传输类型。

function downloadArt(url) 
{ 
    $.ajax(url, { 
     dataType: "binary", 
     processData: false 
    }).done(function (data) { 
     // just my logic to name/create files 
     var filename = url.substr(url.lastIndexOf('/') + 1) + '.png'; 
     var blob = new Blob([data], { type: 'image/png' }); 

     saveAs(blob, filename); 
    }); 
} 

现在,只要你想,在我的情况下,我想将它保存到磁盘,您可以使用创建的斑点。

3.可选:您可以采用FileSaver我用FileSaver

用户的计算机上的文件。JS保存到磁盘下载的文件,如果需要实现这一点,请使用此JavaScript库:

https://github.com/eligrey/FileSaver.js/

我预计这将帮助其他更具体的需求。

+1

ObjectURL由本地定义。对象URL是指向磁盘上的文件的URL。鉴于没有跨域ObjectURL这样的事情,你正在梳理两个不同的概念,因此你的问题使用给定的解决方案。 – BrianFreud 2016-11-24 01:19:05

+1

@BrianFreud我明白了,这不完全是这个问题的答案。但是我仍然认为,自从我到达这里后,它是一个很好的答案,正在寻找一个有点不同的问题“如何从URL获取文件或blob?”的答案。如果你检查你自己的答案,有10个upvotes'它不起作用的情况下跨域请求。 ”。所以有十多个人来这里寻找。我决定然后把它留在这里。 – 2016-12-04 11:30:19

+0

问题是,你的答案故意不回答这个问题。普通的URL和对象的URL是两个完全不同的东西。关于“它在跨域请求的情况下不起作用”的投票结果#,你难道不认为它更好地解释了为什么这在这里几乎是不可能的,并且指向某处显示正常URL的答案,而是通过混合正常的URL和对象URL来混淆这些东西? – BrianFreud 2017-02-12 03:46:42

1

也许有人认为在使用React/Node/Axios时很有用。我在界面上用react-dropzone作为我的Cloudinary图片上传功能。

axios({ 
     method: 'get', 
     url: file[0].preview, // blob url eg. blob:http://127.0.0.1:8000/e89c5d87-a634-4540-974c-30dc476825cc 
     responseType: 'blob' 
    }).then(function(response){ 
     var reader = new FileReader(); 
     reader.readAsDataURL(response.data); 
     reader.onloadend = function() { 
      var base64data = reader.result; 
      self.props.onMainImageDrop(base64data) 
     } 

    })