下载大文件或显示错误
Download a large file or show error
在我们正在开发的网站上,我们有一个下载 link,必须提供给用户。但是,在获取 url 时,服务器可以在 JSON 中提供错误消息(然后将设置适当的 headers 和适当的 http 状态代码)或提供文件。
目前,我们正在使用 iframe 下载此文件,但这会阻止我们查看错误消息。虽然原则上可以做到这一点,但不能做到 cross-domain 并且读取错误数据似乎在浏览器之间有所不同(因为浏览器会将 json 解释为 html 并创建html 个标签)
我考虑过使用 xmlhttprequest2 下载文件并将其提供给用户,但是下载的文件可能很大,因此必须流式传输给用户。
因此,我正在寻找一种方法来根据 http 状态代码下载文件或读取错误消息。
API 设置
我可以根据自己的意愿更改 API,但是 API 被设计为 public API 并且被设计为 REST API。这意味着 API 应该尽可能简单,并且使特定 client-side 代码正常工作的变通方法不应该对其他 client-side 造成任何干扰(因此 API和 client-side 代码是解耦的)。
正在下载的文件在服务器上已加密,只能通过URL中给出的信息解密。因此,分块传输是困难的,因为提取分块需要服务器解密整个文件。
the appropriate headers and an appropriate http status code will then be set
如果该陈述是正确的,您可以对 Cross-site 请求使用与 preflighted requests 相同的概念。预检请求首先使用 OPTIONS
方法向其他域上的资源发送 HTTP 请求,以确定实际请求是否可以安全发送。
在您的情况下,您可以手动发送 HEAD
请求,而不是自动发送 OPTIONS
请求。 HEAD
方法与 GET
相同,只是服务器在响应中不 return 一个 message-body。响应 HEAD
请求的 HTTP headers 中包含的信息应与响应 GET
请求而发送的信息相同。由于您只获取 headers 而不是 body,因此对于大文件甚至任何文件都没有问题,除了 headers.
之外没有任何内容被下载
然后,您可以读取这些 headers 甚至状态代码,并根据此手动预检请求的结果,决定是否应该将文件流式传输给用户或获取错误消息,如果您遇到错误。
在不了解您的项目的情况下使用状态代码的基本实现如下:
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...
}
}
您可以使用单个请求,return 响应作为 Blob
,检查 Blob.type
以确定在何处利用 FileReader
.result
检索 JSON
来自 Blob
的文本并显示错误消息,或使用 URL.createObjectURL
设置 <img>
元素的 src
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);
}
});
您可以 return iframe JS 代码,它会通过 postMessage 向父 window 发送消息,这样您就可以捕获主机 window 中的错误。跨域不会有任何问题,内容可以像以前一样轻松地流式传输到浏览器。
在我们正在开发的网站上,我们有一个下载 link,必须提供给用户。但是,在获取 url 时,服务器可以在 JSON 中提供错误消息(然后将设置适当的 headers 和适当的 http 状态代码)或提供文件。
目前,我们正在使用 iframe 下载此文件,但这会阻止我们查看错误消息。虽然原则上可以做到这一点,但不能做到 cross-domain 并且读取错误数据似乎在浏览器之间有所不同(因为浏览器会将 json 解释为 html 并创建html 个标签)
我考虑过使用 xmlhttprequest2 下载文件并将其提供给用户,但是下载的文件可能很大,因此必须流式传输给用户。
因此,我正在寻找一种方法来根据 http 状态代码下载文件或读取错误消息。
API 设置
我可以根据自己的意愿更改 API,但是 API 被设计为 public API 并且被设计为 REST API。这意味着 API 应该尽可能简单,并且使特定 client-side 代码正常工作的变通方法不应该对其他 client-side 造成任何干扰(因此 API和 client-side 代码是解耦的)。
正在下载的文件在服务器上已加密,只能通过URL中给出的信息解密。因此,分块传输是困难的,因为提取分块需要服务器解密整个文件。
the appropriate headers and an appropriate http status code will then be set
如果该陈述是正确的,您可以对 Cross-site 请求使用与 preflighted requests 相同的概念。预检请求首先使用 OPTIONS
方法向其他域上的资源发送 HTTP 请求,以确定实际请求是否可以安全发送。
在您的情况下,您可以手动发送 HEAD
请求,而不是自动发送 OPTIONS
请求。 HEAD
方法与 GET
相同,只是服务器在响应中不 return 一个 message-body。响应 HEAD
请求的 HTTP headers 中包含的信息应与响应 GET
请求而发送的信息相同。由于您只获取 headers 而不是 body,因此对于大文件甚至任何文件都没有问题,除了 headers.
然后,您可以读取这些 headers 甚至状态代码,并根据此手动预检请求的结果,决定是否应该将文件流式传输给用户或获取错误消息,如果您遇到错误。
在不了解您的项目的情况下使用状态代码的基本实现如下:
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...
}
}
您可以使用单个请求,return 响应作为 Blob
,检查 Blob.type
以确定在何处利用 FileReader
.result
检索 JSON
来自 Blob
的文本并显示错误消息,或使用 URL.createObjectURL
<img>
元素的 src
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);
}
});
您可以 return iframe JS 代码,它会通过 postMessage 向父 window 发送消息,这样您就可以捕获主机 window 中的错误。跨域不会有任何问题,内容可以像以前一样轻松地流式传输到浏览器。