Ich habe eine Struts2-Aktion auf der Serverseite zum Herunterladen von Dateien.
<action name="download" class="com.xxx.DownAction">
<result name="success" type="stream">
<param name="contentType">text/plain</param>
<param name="inputName">imageStream</param>
<param name="contentDisposition">attachment;filename={fileName}</param>
<param name="bufferSize">1024</param>
</result>
</action>
Wenn ich die Aktion jedoch mit der jQuery:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
in Firebug sehe ich, dass die Daten mit dem Binärstrom abgerufen werden. Ich frage mich, wie man das Fenster zum Herunterladen von Dateien öffnet, mit dem der Benutzer die Datei lokal speichern kann?
Update für moderne Browser 2019
Dies ist der Ansatz, den ich jetzt mit einigen Vorbehalten empfehlen würde:
fetch('https://jsonplaceholder.typicode.com/todos/1')
.then(resp => resp.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
// the filename you want
a.download = 'todo-1.json';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
alert('your file has downloaded!'); // or you know, something with better UX...
})
.catch(() => alert('oh no!'));
2012 Original jQuery/iframe/Cookie-basierter Ansatz
Bluish hat vollkommen recht, man kann es nicht über Ajax machen, weil JavaScript keine Dateien direkt auf dem Computer eines Benutzers speichern kann (aus Sicherheitsgründen). Wenn Sie die URL des Hauptfensters's auf Ihren Dateidownload richten, haben Sie leider nur wenig Kontrolle über die Benutzererfahrung, wenn ein Dateidownload stattfindet.
Ich habe jQuery File Download, die für eine "Ajax like" Erfahrung mit Datei-Downloads komplett mit OnSuccess und OnFailure Rückrufe für eine bessere Benutzererfahrung zu bieten. Werfen Sie einen Blick auf meinen Blogpost über das häufige Problem, das das Plugin löst, und einige Möglichkeiten, es zu verwenden, sowie eine Demo von jQuery File Download in Aktion. Hier ist die Quelle
Hier ist ein einfaches Anwendungsbeispiel, das das Plugin Quelle mit Versprechen verwendet. Die Demo-Seite enthält auch viele andere, 'bessere UX' Beispiele.
$.fileDownload('some/file.pdf')
.done(function () { alert('File download a success!'); })
.fail(function () { alert('File download failed!'); });
Je nachdem, welche Browser Sie unterstützen müssen, können Sie https://github.com/eligrey/FileSaver.js/ verwenden, das eine explizitere Kontrolle als die IFRAME-Methode von jQuery File Download erlaubt.
Niemand hat das hier gepostet @Pekka's Lösung... also werde ich es posten. Es kann jemandem helfen.
Sie müssen das nicht über Ajax machen. Verwenden Sie einfach
window.location="download.action?para1=value1...."
1. Framework-unabhängig: Servlet lädt Datei als Anhang herunter
<!-- with JS -->
<a href="javascript:window.location='downloadServlet?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadServlet?param1=value1" >download</a>
2. Struts2-Framework: Aktion zum Herunterladen der Datei als Anhang
<!-- with JS -->
<a href="javascript:window.location='downloadAction.action?param1=value1'">
download
</a>
<!-- without JS -->
<a href="downloadAction.action?param1=value1" >download</a>
Es wäre besser, <s:a>
Tag zu verwenden, der mit OGNL auf eine URL zeigt, die mit <s:url>
Tag erstellt wurde:
<!-- without JS, with Struts tags: THE RIGHT WAY -->
<s:url action="downloadAction.action" var="url">
<s:param name="param1">value1</s:param>
</s:ulr>
<s:a href="%{url}" >download</s:a>
In den oben genannten Fällen müssen Sie den Header Content-Disposition in die Antwort schreiben, der angibt, dass die Datei heruntergeladen (attachment
) und nicht vom Browser geöffnet (inline
) werden muss. Sie müssen auch den Inhaltstyp angeben, und vielleicht möchten Sie den Dateinamen und die Länge der Datei hinzufügen (damit der Browser einen realistischen Fortschrittsbalken zeichnen kann).
Zum Beispiel beim Herunterladen einer ZIP-Datei:
response.setContentType("application/zip");
response.addHeader("Content-Disposition",
"attachment; filename=\"name of my file.zip\"");
response.setHeader("Content-Length", myFile.length()); // or myByte[].length...
Mit Struts2 (es sei denn, Sie verwenden die Action als Servlet, z. B. einen Hack für direktes Streaming), müssen Sie nichts direkt in die Antwort schreiben; es genügt, den Stream result type zu verwenden und ihn in struts.xml zu konfigurieren: BEISPIEL
<result name="success" type="stream">
<param name="contentType">application/zip</param>
<param name="contentDisposition">attachment;filename="${fileName}"</param>
<param name="contentLength">${fileLength}</param>
</result>
3. Framework-unabhängig (/ Struts2 Framework): Servlet(/Action) öffnet Datei innerhalb des Browsers
Wenn Sie die Datei innerhalb des Browsers öffnen wollen, anstatt sie herunterzuladen, muss die Content-disposition auf inline gesetzt werden, aber das Ziel kann nicht die aktuelle Fensterposition sein; Sie müssen ein neues Fenster anvisieren, das durch Javascript, einen <iframe>
in der Seite oder ein neues Fenster, das on-the-fly mit dem "discussed" target="_blank" erstellt wurde:
<!-- From a parent page into an IFrame without javascript -->
<a href="downloadServlet?param1=value1" target="iFrameName">
download
</a>
<!-- In a new window without javascript -->
<a href="downloadServlet?param1=value1" target="_blank">
download
</a>
<!-- In a new window with javascript -->
<a href="javascript:window.open('downloadServlet?param1=value1');" >
download
</a>