2016-07-21 146 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