Firebase's documentation covers downloading an image if you call storage and getDownloadURL, and I have this working fine (straight from the docs):
storageRef.child('images/stars.jpg').getDownloadURL().then(function(url) {
// `url` is the download URL for 'images/stars.jpg'
// This can be downloaded directly:
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(event) {
var blob = xhr.response;
};
xhr.open('GET', url);
xhr.send();
// Or inserted into an <img> element:
var img = document.getElementById('myimg');
img.src = url;
}).catch(function(error) {
// Handle any errors
});
However, I already have a URL and want to download an image without calling firebase storage. This is my attempt:
var url = "https://firebasestorage.googleapis.com/v0/b/somerandombucketname..."
console.log(url);
// This can be downloaded directly:
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function(event) {
var blob = xhr.response;
};
xhr.open('GET', url);
xhr.send();
But, no file is downloaded and no error is shown in the browser's development tools.
Note: I do know the URL is correct because if I put URL directly into my browser search bar, I am able to access the file and download it.
Does anyone know how to download an image using a Download URL that you already have (without calling Firebase Storage as they do in the docs)?
This ended up working for me:
var url = "https://firebasestorage.googleapis.com/v0/b/somerandombucketname..."
var filename = url.substring(url.lastIndexOf("/") + 1).split("?")[0];
var xhr = new XMLHttpRequest();
xhr.responseType = 'blob';
xhr.onload = function() {
var a = document.createElement('a');
a.href = window.URL.createObjectURL(xhr.response);
a.download = "fileDownloaded.filetype"; // Name the file anything you'd like.
a.style.display = 'none';
document.body.appendChild(a);
a.click();
};
xhr.open('GET', url);
xhr.send();
This is essentially creating an a href to the URL I have and then clicking the a href programmatically when the xhr response is received.
It is not clear to me why the first way doesn't work as well, but hopefully this helps others that face the same issue.
Related
I have this code that correctly works on most of browsers except IE:
<a href="http://xxx.xxx.xxx.xxx/presets/current" download="configuration.bin">
Save
</a>
the problem is that download parameter doesn't work on IE.
To correct it I've tried this code
var request = new XMLHttpRequest();
request.open('GET', "http://xxx.xxx.xxx.xxx/presets/current", true);
request.responseType = 'blob';
request.onload = function() {
var reader = new FileReader();
reader.readAsDataURL(request.response);
reader.onload = function(e){
var blob = new Blob( [e.target.result] );
navigator.msSaveBlob( blob, 'configuration.bin' );
};
};
request.send();
On AngularJS I've also tried using $http like this code:
$http({method: 'GET', url: "http://xxx.xxx.xxx.xxx/presets/current"})
.success(function(data, status, headers, config) {
var blob = new Blob([data]);
navigator.msSaveBlob( blob, 'configuration.bin' );
})
The problem is that the file size downloaded on Chrome is 134K and the file downloaded on IE with this code is 180K
Question: How could I save file exactly as I get it?
In IE, you can only use msSaveBlob to download files and you need to set the blob type correctly according to your demand. The cross-browser method should be like this:
//change to the type you need
var blob = new Blob([byteArray], { type: 'application/pdf' });
//output file name
var fileName = "test.pdf";
//detect whether the browser is IE/Edge or another browser
if (window.navigator && window.navigator.msSaveOrOpenBlob) {
//To IE or Edge browser, using msSaveorOpenBlob method to download file.
window.navigator.msSaveBlob(blob, fileName);
} else {
//To another browser, create a tag to downlad file.
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
document.body.appendChild(a);
a.setAttribute('style', 'display: none');
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
a.remove();
}
I use this method to download file and the size is the same in IE and Chrome. You could also refer to these similar threads: link1, link2.
I would like to load a file from my storage (Azure) where i don't know the file extension from but i do know the filename, after i would like to use the right file for the src.video. Basically feed every optional video source into videoJS.
this works, but only for two predefined files (mp4/mov):
var video = document.getElementById('my-player')
fileExists()
function fileExists() {
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'https://linktovideo + '.mp4', true);
xhr.send();
xhr.onreadystatechange = processRequest;
function processRequest(e) {
console.log(xhr.status)
if (xhr.status == 200) {
console.log("MP4 video)
video.src = 'https://linktovideo' + '.mp4';
} else {
console.log("MOV video")
video.src = 'https://linktovideo' + '.mov';
}
}
}
what i like to do is something as this, make a general search for the file (.*);
var xhr = new XMLHttpRequest();
xhr.open('HEAD', 'https://linktovideo + '.*', true);
xhr.send();
xhr.onreadystatechange = processRequest;
then from the actual file extract the extension and glue that to
video.src = 'https://linktovideo' + '.webm';
would something like this be possible? Now of course the XMLrequest returns 404
any ideas or suggestions?
Thank you for reading!
I want to open a PDF from a REST backend that gets loaded via XHR in a new tab with specified filename and Authorization header.
So far I managed to download it with this (incl. auth headers and filename):
// saves XHR stream as file with configurable filename
downloadXHRFile:function(endpoint,data,method,filename,errorcallback,mimetype){
bsLoadingOverlayService.start();
var def = $q.defer();
var token = localStorageService.get('token');
var xhr = new XMLHttpRequest();
xhr.open(method, CONFIG.URL+endpoint, true);
xhr.setRequestHeader('Authorization', 'Bearer '+token);
xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = 'arraybuffer';
xhr.onload = function(e) {
if (this.status == 200) {
var blob=new Blob([this.response], {type:mimetype});
var link=document.createElement('a');
link.href=window.URL.createObjectURL(blob);
link.download=filename;
link.click();
bsLoadingOverlayService.stop();
}else{
bsLoadingOverlayService.stop();
errorcallback(xhr.statusText);
}
def.resolve();
};
xhr.send(
JSON.stringify(data)
);
return def;
},
Further I managed to open it in a new tab with the following code (incl. auth headers).
Unfortunately the URL (and by that the filename) looks like this:
blob:http://localhost:3000/0857f080-d152-48c6-b5fb-6e56292db651
Probably it can be solved somehow like above but I cant find the solution.
Does someone have a clever idea how I could set the filename in the new Tab?
// opens XHR filestream in tab
openXHRFile: function(endpoint,filename,errorcallback){
var token = localStorageService.get('token');
var our_url = CONFIG.URL+endpoint;
var win = window.open('_blank');
downloadFile(our_url, function(blob) {
var url = URL.createObjectURL(blob);
win.location = url;
});
function downloadFile(url, success) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.setRequestHeader("Authorization", 'Bearer '+token);
// xhr.setRequestHeader('Content-Type', 'application/json');
xhr.responseType = "blob";
xhr.onreadystatechange = function() {
if (xhr.readyState == 4) {
if (success) success(xhr.response);
}else{
}
};
xhr.send(null);
}
},
I have used below code to download image with given name. But this seems does not download image with it's own image extension.
Here is HTML
<a id="btnDownload" href="www.mywebsite.com/images/myimage.jpg" onClick="downloadImage(www.mywebsite.com/images/myimage.jpg);" >download</a>
and code
function downloadImage(sUrl){
window.URL = window.URL || window.webkitURL;
var xhr = new XMLHttpRequest();
xhr.open('GET', sUrl, true);
xhr.responseType = 'blob';
xhr.onload = function(e) {
var res = xhr.response;
var blob = new Blob([res], {type:'image'});
url = window.URL.createObjectURL(blob);
var a = document.createElement("a");
a.href = url;
a.download = "My image name";
document.body.appendChild(a);
a.click();
};
xhr.send();
}
What i want is i want downloaded image with "My image name"."extension". Here image does have alternative extension like jpeg, png, gif.
But this code always download file without extension. Any changes here?
To get the extension in your example you could do:
a.download = "My image Name." + window.URL.split('.').pop();
Yet I would work with different data-attributes:
<html>
<!--
You can put the href and the name you want to see in different data attributes.
Also one can add IE support.
-->
<head>
<script>
//e:=<a [data-name] [data-href]>
function downloadMe(e){
var tF = e.getAttribute('data-name');
var tURL = e.getAttribute('data-href')
var tR = new XMLHttpRequest();
tR.open('GET', tURL, true);
tR.responseType = 'blob';
tR.onload = function(e){
var tB = this.response;
if(window.top.navigator.msSaveOrOpenBlob){
//Store Blob in IE
window.top.navigator.msSaveOrOpenBlob(tB, tF)
}
else{
//Store Blob in others
var tA = document.body.appendChild(document.createElement('a'));
tA.href = URL.createObjectURL(tB);
tA.download = tF;
tA.style.display = 'none';
tA.click();
tA.parentNode.removeChild(tA)
}
};
tR.send();
return false
}
</script>
</head>
<body>
<a href = '#' data-href = 'A.png' data-name = 'My Name.png' onclick = 'return downloadMe(this)'>download</a>
</body>
</html>
I am programming an embedded Device in C with a webserver. One Task is to download files from this devices. I want to Download serveral files at once, so i created an ajax-request, which using POST-Request and a bunch of filenames to return a zip-file (i create these zip-file on my own on the device). Everything works fine, but the dialog save as appears after the whole zip-file was transmitted.
At server-side the device is sending the 200 OK-, Content-Type: application/octet-stream- and Content-Disposition: attachment; filename="testzip.zip"-headers.
At client-side i using this javascript-code(got this from stackoverlfow: Handle file download from ajax post):
function downloadFiles(filenames) {
var xhr = new XMLHttpRequest();
xhr.open('POST', /file-save/, true);
xhr.responseType = 'arraybuffer';
xhr.onload = function () {
if (this.status === 200) {
var filename = "test.zip";
var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([this.response], { type: type });
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
};
xhr.send(filenames);
}
The if-statement if (this.status === 200) is reached, when the whole file is transmitted. If the size of the file is small, there is not a problem, because the user isn't recognizing the lack of time. But is the file about 50MB the user can't see any download although the file is downloading. In my opinion the reason is a.click(), because the click-method imitades the begin of the download.
Is there sombody who can help me out with a solution or some hints?
By the way, jquery isn't an option!.
Thanks for any help
EDIT: my goal is to download a file like on every webpage with large files, where i get a dialog with the location to save and i can see the download-progress.
SOLUTION(Hint from Herr Derb):
function downloadFiles(filenames) {
var xhr = new XMLHttpRequest();
xhr.open('POST', /file_save/, true);
xhr.onload = function () {
if (this.status === 200) {
var mydisp = xhr.getResponseHeader('Content-Disposition');
var save_response = xhr.responseText;
var var_json_format = JSON.parse(save_response);
/* check for errors */
if(var_json_format["error"]) {
return;
} else {
status = _.findWhere(var_json_format["link"], {id : 'status'}).value;
download_id = _.findWhere(var_json_format["link"], {id : 'download_id'}).value;
}
if(status != "active") {
return;
}
var filename = "test.zip";
var downloadUrl = "/file_save/" + download_id;
var a = document.createElement("a");
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
document.body.removeChild(a);
setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
};
xhr.send(filenames);
return;
}
Your first request should only create the zip file on your server and return a link to reach it. After you received that link on the client site, simply execute it. This way, everything will happen as you desire, as it will be a regular file download.
And ss soon the download is finished, your free to delete the file again.