2016-07-21 84 views
0

在我們正在處理的網站上,我們有一個下載鏈接,必須提供給用戶。但是,在獲取url時,服務器可以在JSON中提供錯誤消息(將設置適當的頭文件和適當的http狀態代碼)或提供文件。下載大文件或顯示錯誤

目前,我們正在使用iframe下載此文件,但這會阻止我們查看錯誤消息。雖然原則上可以這樣做,但它不能跨域進行,並且讀取錯誤數據似乎在瀏覽器之間不同(因爲瀏覽器會將json解釋爲html並在其周圍創建html標記)

I已經考慮使用xmlhttprequest2來下載文件並將其提供給用戶,但是下載的文件可能很大,因此必須將其傳輸給用戶。

因此,我正在尋找一種方法來下載文件或根據http狀態代碼讀取錯誤消息。

API設置

我能到API的轉變讓我的願望,但是API的設計是一個公共API,並且被設計爲REST API。這意味着,API應該儘可能簡單,並且使特定客戶端代碼工作的解決方法不應該對其他客戶端造成任何困惑(因此API和客戶端代碼是分離的)。

正在下載的文件在服務器上被加密,只能通過URL中給出的信息進行解密。因此,分塊傳輸很困難,因爲提取塊需要服務器解密整個文件。

+0

你有控制服務器響應嗎?你可以改變回應是一個錯誤代碼和錯誤消息或成功的代碼和文件的網址?如果是這樣,你可以做一個Ajax調用,併成功重定向到URL。如果這不起作用,請解釋一下你的設置可以防止這種情況。 – TinMonkey

+0

期望什麼'MIME'類型的文件? – guest271314

+0

@TinMonkey,是的,我喜歡。但總的來說,任何錯誤都是一個例外,我寧願提出一個請求,但我只是開始使用下面描述的HEAD方法來實現。它也涉及到一個REST API,所以這樣的重定向並不適合設計,但是HEAD當然會採用一種方法:)。 – user23127

回答

3

相應的頭和適當的HTTP狀態代碼將被設置

如果這種說法是正確的,你可以用同樣的概念preflighted requests的跨站點請求。預先發送請求首先發送帶有OPTIONS方法的HTTP請求到其他域上的資源,以確定實際請求是否安全發送。

在您的情況下,您可以手動發送HEAD請求,而不是自動發送OPTIONS請求。 HEAD方法與GET相同,只是服務器不在響應中返回消息主體。響應HEAD請求的HTTP頭中包含的信息應該與爲響應GET請求而發送的信息相同。由於您只是獲取標題而不是正文,所以對於大文件甚至任何文件都沒有問題,除了標題以外,沒有任何內容可以下載。

然後,您可以閱讀這些頭文件或甚至狀態碼,並根據手動預檢的請求的結果,決定是將文件流式傳輸給用戶還是獲取錯誤消息(如果遇到錯誤。

不使用狀態代碼項目的知識基本實現可能是以下幾點:

function canDownloadFile(url, callback) 
{ 
    var http = new XMLHttpRequest(); 
    http.open('HEAD', url); 
    http.onreadystatechange = function() { 
    if (http.readyState === XMLHttpRequest.DONE) { 
     callback(http.status); 
    } 
    }; 

    http.send(); 
} 

var canDownloadCallback = function (statusCode) { 
    if (statusCode === 200) { 
    // The HEAD request returned an OK status code, the GET will do the same, 
    // let's download the file... 
    } else { 
    // The HEAD request returned something else, something is wrong, 
    // let's fetch the error message and maybe display it... 
    } 
} 
+0

嘿,這正是我現在正在執行的!我希望有一個單一的請求替代方案,但如果不是,我會接受你的答案。 – user23127

0

你可以使用單一的請求,返回響應爲Blob,檢查Blob.type,以確定利用FileReader.result檢索使用URL.createObjectURL

var result = document.querySelector("div"); 

fetch("/path/to/resource") 
.then(response => response.blob()) 
.then(blob => { 
    if (blob.type === "application/json") { 
    var reader = new FileReader(); 
    reader.onload = (e) => { 
     result.innerHTML = JSON.parse(e.target.result).error 
    }; 
    reader.readAsText(blob); 
    } else { 
    var img = document.createElement("img"); 
    img.src = URL.createObjectURL(blob); 
    result.appendChild(img); 
    } 
}); 
Blob和顯示錯誤信息,或者設置 <img>元件的 src JSON文本3210

plnkr http://plnkr.co/edit/wrzLNm1Sp4k1mfNrYOlQ?p=preview

+0

這是否適用於大文件?這會將整個文件加載到內存中,對嗎? – user23127

+0

@ user23127 _「這是否適用於大文件?」_您是否嘗試過? – guest271314

+0

我很確定它沒有。 – user23127

1

您可以返回iframe JS代碼,它將通過postMessage將消息發送到父窗口,這樣您可以捕獲主機窗口中的錯誤。跨域不會有任何問題,並且內容很容易會像以前一樣流式傳輸到瀏覽器。

+0

這將需要我適應服務器響應的客戶端響應,不應該是一個瀏覽器。 – user23127