2012-08-09 104 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) 
     } 

    })