Downloading A File (or Handling An HTTP Error) On Click
Solution 1:
You can use XMLHttpRequest()
, with error
event attached to request resource. If request is not successful, error should be handled at error
event handler of XMLHttpRequest()
.
You could alternatively use fetch()
to achieve same result.
Set .responseType
to "blob"
at XMLHttpRequest
or return response.blob()
at fetch()
. Create a new Blob
with type
set to "application/octet-stream"
, call window.open()
with URL.createObjectURL()
as parameter where Blob
is parameter to .createObjectURL()
, which should open Save File
dialog.
You can chain .catch()
to fetch()
to handle errors.
<body>
<a href="#" data-link="file.txt">download file.txt</a>
<a href="#" data-link="http://stackoverflow.com">download stackoverflow.com</a>
<script>
var request = (path) =>
fetch(path)
.then(response => response.blob())
.then(blob => window.open(
URL.createObjectURL(
new Blob([blob], {
type: "application/octet-stream"
})
), "_self"))
// handle request error
.catch((err) => {console.log(err); throw err});
var a = document.querySelectorAll("a");
for (let link of a) {
link.onclick = (e) => {
e.preventDefault();
request(e.target.dataset.link)
.catch((err) => {
alert(err.message + "\ndownload of " + e.target.dataset.link + " error")
})
}
}
</script>
</body>
plnkr http://plnkr.co/edit/J40cPoLJ2WwESRzsSRhL?p=preview
Alternatively using <a>
element, download
attribute to suggest file name at Save File
dialog
<body>
<a href="#" data-link="file.txt">download file.txt</a>
<a href="#" data-link="http://stackoverflow.com">download stackoverflow.com</a>
<script>
var request = (path) =>
fetch(path)
.then(response => response.blob())
.then(blob => {
var type = blob.type.split("/").pop();
type = type === "plain" ? "txt" : type;
var d = document.createElement("a");
d.className = "download";
d.download = "file-" + new Date().getTime() + "." + type;
d.href = URL.createObjectURL(blob);
document.body.appendChild(d);
d.click();
d.parentElement.removeChild(d);
})
// handle request error
.catch((err) => {console.log(err); throw err});
var a = document.querySelectorAll("a[href='#']");
for (let link of a) {
link.onclick = (e) => {
console.log(e)
e.preventDefault();
request(e.target.dataset.link)
.catch((err) => {
alert(err.message + "\ndownload of " + e.target.dataset.link + " error")
})
}
}
</script>
</body>
Solution 2:
For handling the download of the file, the download attribute could be a solution (with polyfill).
But for the handling the HTTP errors in my opinion the best solution is using some back-end proxy which will check the HTTP headers and also will force the browser to download a specific file.
Post a Comment for "Downloading A File (or Handling An HTTP Error) On Click"