Was ist der beste browserübergreifende Weg, um einen Download-Dialog zu öffnen (nehmen wir an, wir können content-disposion:attachment in den Headern einstellen), ohne von der aktuellen Seite weg zu navigieren oder Popups zu öffnen, was im Internet Explorer (IE) 6 nicht gut funktioniert.
Antworten
Zu viele Anzeigen?Ich habe nach einer guten Möglichkeit gesucht, Javascript zu verwenden, um den Download einer Datei zu initiieren, genau wie diese Frage vorschlägt. Allerdings waren diese Antworten nicht hilfreich. Ich habe dann einige xbrowser Tests und haben festgestellt, dass ein iframe funktioniert am besten auf allen modernen Browsern IE>8.
downloadUrl = "http://example.com/download/file.zip";
var downloadFrame = document.createElement("iframe");
downloadFrame.setAttribute('src',downloadUrl);
downloadFrame.setAttribute('class',"screenReaderText");
document.body.appendChild(downloadFrame);
class="screenReaderText"
ist meine Klasse zur Gestaltung von Inhalten, die zwar vorhanden, aber nicht sichtbar sind.
css:
.screenReaderText {
border: 0;
clip: rect(0 0 0 0);
height: 1px;
margin: -1px;
overflow: hidden;
padding: 0;
position: absolute;
width: 1px;
}
gleich wie .visuallyHidden in html5boilerplate
Ich ziehe dies der Javascript-Methode window.open vor, da die iframe-Methode bei einem defekten Link einfach nichts tut, im Gegensatz zur Weiterleitung zu einer leeren Seite, die besagt, dass die Datei nicht geöffnet werden konnte.
window.open(downloadUrl, 'download_window', 'toolbar=0,location=no,directories=0,status=0,scrollbars=0,resizeable=0,width=1,height=1,top=0,left=0');
window.focus();
HTML5 verwenden Blob Objekt-URL-Datei-API:
/**
* Save a text as file using HTML <a> temporary element and Blob
* @see https://stackoverflow.com/questions/49988202/macos-webview-download-a-html5-blob-file
* @param fileName String
* @param fileContents String JSON String
* @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName,fileContents) {
if(typeof(Blob)!='undefined') { // using Blob
var textFileAsBlob = new Blob([fileContents], { type: 'text/plain' });
var downloadLink = document.createElement("a");
downloadLink.download = fileName;
if (window.webkitURL != null) {
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
}
else {
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = document.body.removeChild(event.target);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
} else {
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.onclick = document.body.removeChild(event.target);
pp.click();
}
}//saveBlobAsFile
/**
* Save a text as file using HTML <a> temporary element and Blob
* @see https://stackoverflow.com/questions/49988202/macos-webview-download-a-html5-blob-file
* @param fileName String
* @param fileContents String JSON String
* @author Loreto Parisi
*/
var saveBlobAsFile = function(fileName, fileContents) {
if (typeof(Blob) != 'undefined') { // using Blob
var textFileAsBlob = new Blob([fileContents], {
type: 'text/plain'
});
var downloadLink = document.createElement("a");
downloadLink.download = fileName;
if (window.webkitURL != null) {
downloadLink.href = window.webkitURL.createObjectURL(textFileAsBlob);
} else {
downloadLink.href = window.URL.createObjectURL(textFileAsBlob);
downloadLink.onclick = document.body.removeChild(event.target);
downloadLink.style.display = "none";
document.body.appendChild(downloadLink);
}
downloadLink.click();
} else {
var pp = document.createElement('a');
pp.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(fileContents));
pp.setAttribute('download', fileName);
pp.onclick = document.body.removeChild(event.target);
pp.click();
}
} //saveBlobAsFile
var jsonObject = {
"name": "John",
"age": 31,
"city": "New York"
};
var fileContents = JSON.stringify(jsonObject, null, 2);
var fileName = "data.json";
saveBlobAsFile(fileName, fileContents)
Die Änderung der Position des Fensters kann zu Problemen führen, insbesondere wenn Sie eine dauerhafte Verbindung wie einen Websocket haben. Daher greife ich immer auf die gute alte iframe-Lösung zurück.
HTML
<input type="button" onclick="downloadButtonClicked()" value="Download"/>
...
...
...
<iframe style="display:none;" name="hiddenIframe" id="hiddenIframe"></iframe>
Javascript
function downloadButtonClicked() {
// Simulate a link click
var url = 'your_download_url_here';
var elem = document.createElement('a');
elem.href = url;
elem.target = 'hiddenIframe';
elem.click();
}
Wenn der Link auf eine gültige Datei-URL verweist, genügt die Zuweisung von window.location.href.
Manchmal ist der Link jedoch nicht gültig und ein iFrame ist erforderlich.
Tun Sie Ihre normale event.preventDefault, um das Fenster vom Öffnen zu verhindern, und wenn Sie jQuery verwenden, wird dies funktionieren:
$('<iframe>').attr('src', downloadThing.attr('href')).appendTo('body').on("load", function() {
$(this).remove();
});
Nach stundenlangen Versuchen ist die Funktion geboren :) Ich hatte ein Szenario, wo ich Loader in der Zeit anzeigen musste, während die Datei für den Download vorbereitet wird:
Funktioniert in Chrome, Safari und Firefox
function ajaxDownload(url, filename = 'file', method = 'get', data = {}, callbackSuccess = () => {}, callbackFail = () => {}) {
$.ajax({
url: url,
method: 'GET',
xhrFields: {
responseType: 'blob'
},
success: function (data) {
// create link element
let a = document.createElement('a'),
url = window.URL.createObjectURL(data);
// initialize
a.href = url;
a.download = filename;
// append element to the body,
// a must, due to Firefox
document.body.appendChild(a);
// trigger download
a.click();
// delay a bit deletion of the element
setTimeout(function(){
window.URL.revokeObjectURL(url);
document.body.removeChild(a);
}, 100);
// invoke callback if any
callbackSuccess(data);
},
error: function (err) {
// invoke fail callback if any
callbackFail(err)
}
});