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 jedoch die Aktion mit jQuery aufrufe:
$.post(
"/download.action",{
para1:value1,
para2:value2
....
},function(data){
console.info(data);
}
);
In Firebug sehe ich, dass die Daten mit dem Binär-Stream abgerufen werden . Ich frage mich, wie ich das Fenster zum Herunterladen von Dateien öffnen kann, mit dem der Benutzer die Datei lokal speichern kann.
Antworten:
2019 Update moderner Browser
Dies ist der Ansatz, den ich jetzt mit ein paar Einschränkungen empfehlen würde:
2012 Ursprünglicher jQuery / iframe / Cookie-basierter Ansatz
Bluish hat diesbezüglich völlig Recht. Sie können dies nicht über Ajax tun, da JavaScript Dateien aus Sicherheitsgründen nicht direkt auf dem Computer eines Benutzers speichern kann. Leider zeigt das HauptfensterWenn Sie URL auf Ihren Dateidownload nur wenig Kontrolle darüber, wie die Benutzererfahrung beim Herunterladen von Dateien ist.
Ich habe jQuery File Download erstellt, das eine "Ajax-ähnliche" Erfahrung mit Dateidownloads mit OnSuccess- und OnFailure-Rückrufen ermöglicht, um eine bessere Benutzererfahrung zu erzielen. Werfen Sie einen Blick auf meinen Blog-Beitrag über das häufig auftretende Problem, das das Plugin löst, und einige Verwendungsmöglichkeiten sowie eine Demo von jQuery File Download in Aktion . Hier ist die Quelle
Hier ist eine einfache Anwendungsfall-Demo unter Verwendung der Plugin- Quelle mit Versprechungen. Die Demoseite enthält auch viele andere, bessere UX-Beispiele.
Abhängig davon, welche Browser Sie unterstützen müssen, können Sie möglicherweise https://github.com/eligrey/FileSaver.js/ verwenden, was eine explizitere Steuerung ermöglicht als die IFRAME-Methode, die jQuery File Download verwendet.
quelle
Niemand hat diese @ Pekka-Lösung gepostet ... also werde ich sie posten. Es kann jemandem helfen.
Sie müssen dies nicht über Ajax tun. Benutz einfach
quelle
window.open(<url>, '_blank');
um sicherzustellen, dass der Download Ihren aktuellen Browserinhalt nicht ersetzt (unabhängig vom Content-Disposition-Header).POST
Anfrage.Sie können mit HTML5
NB: Die zurückgegebenen Dateidaten MÜSSEN base64-codiert sein, da Sie keine JSON-Binärdaten codieren können
In meiner
AJAX
Antwort habe ich eine Datenstruktur, die so aussieht:Das bedeutet, dass ich Folgendes tun kann, um eine Datei über AJAX zu speichern
Die Funktion base64ToBlob wurde von hier übernommen und muss in Übereinstimmung mit dieser Funktion verwendet werden
Dies ist gut, wenn Ihr Server die zu speichernden Dateidaten speichert. Ich habe jedoch nicht ganz herausgefunden, wie man einen HTML4-Fallback implementieren würde
quelle
a.click()
scheint in Firefox nicht zu funktionieren ... Irgendeine Idee?a
zum Dom hinzufügen , damit dieser Code funktioniert, und / oder dasrevokeObjectURL
Teil entfernen :document.body.appendChild(a)
var bytechars = atob(base64)
wird ein Fehler ausgegebenJavaScript runtime error: InvalidCharacterError
. Ich verwende Chrome Version 75.0.3770.142, aber ich weiß nicht, was hier falsch ist.1. Framework-Agnostiker: Servlet-Download-Datei als Anhang
2. Struts2 Framework: Aktion zum Herunterladen der Datei als Anhang
Es ist besser, ein
<s:a>
Tag zu verwenden, das mit OGNL auf eine mit erstellte URL zeigt<s:url>
Tag :In den obigen Fällen, Sie müssen das schreiben Content-Disposition - Header an die Antwort , die Angabe , dass die Datei Bedarf heruntergeladen werden (
attachment
) und nicht vom Browser geöffnet (inline
). Du brauchst den Inhaltstyp angeben und möchten möglicherweise den Dateinamen und die Länge hinzufügen (damit der Browser einen realistischen Fortschrittsbalken zeichnen kann).Zum Beispiel beim Herunterladen einer ZIP:
Mit Struts2 (es sei denn, Sie verwenden die Aktion als Servlet, z. B. einen Hack für direktes Streaming ), müssen Sie nichts direkt in die Antwort schreiben. Die einfache Verwendung des Stream-Ergebnistyps und dessen Konfiguration in struts.xml funktioniert wie folgt: BEISPIEL
3. Framework-Agnostiker (/ Struts2-Framework): Servlet (/ Action) öffnet Datei im Browser
Wenn Sie die Datei im Browser öffnen möchten, anstatt sie herunterzuladen, muss die Inhaltsdisposition auf Inline eingestellt sein , aber das Ziel kann nicht der aktuelle Speicherort des Fensters sein. Sie müssen auf ein neues Fenster abzielen, das mit Javascript erstellt wurde,
<iframe>
auf die Seite oder auf ein neues Fenster, das im laufenden Betrieb mit dem "diskutierten" target = "_ blank" erstellt wurde:quelle
too long url
Fehler erhalten.Der einfache Weg, um den Browser zum Herunterladen einer Datei zu veranlassen, besteht darin, die Anfrage wie folgt zu stellen:
Dies öffnet das Popup-Fenster zum Herunterladen des Browsers.
quelle
Ich habe wenig Funktion als Workaround-Lösung erstellt (inspiriert vom @ JohnCulviner-Plugin):
Demo mit Klickereignis:
quelle
Ich stand vor dem gleichen Problem und löste es erfolgreich. Mein Anwendungsfall ist dies.
" JSON-Daten an den Server senden und eine Excel-Datei empfangen. Diese Excel-Datei wird vom Server erstellt und als Antwort an den Client zurückgegeben. Laden Sie diese Antwort als Datei mit benutzerdefiniertem Namen im Browser herunter. "
Das obige Snippet macht nur folgendes
Hier müssen wir einige Dinge auf der Serverseite sorgfältig einstellen. Ich habe einige Header in Python Django HttpResponse gesetzt. Sie müssen sie entsprechend einstellen, wenn Sie andere Programmiersprachen verwenden.
Da ich hier xls (excel) herunterlade, habe ich contentType auf über eins eingestellt. Sie müssen es entsprechend Ihrem Dateityp einstellen. Mit dieser Technik können Sie beliebige Dateien herunterladen.
quelle
HTMLAnchorElement.download
, denke ich darüber nach, es mit der proprietären msSaveOrOpenBlob- Methode zu kombinieren .Ok, basierend auf ndpus Code ist hier eine verbesserte (glaube ich) Version von ajax_download; -
Verwenden Sie dies so; -
Die Parameter werden als richtige Post-Parameter gesendet, als ob sie von einer Eingabe stammen, und nicht als json-codierte Zeichenfolge wie im vorherigen Beispiel.
CAVEAT: Seien Sie vorsichtig hinsichtlich des Potenzials einer variablen Injektion in diese Formen. Es gibt möglicherweise eine sicherere Möglichkeit, diese Variablen zu codieren. Alternativ erwägen Sie, ihnen zu entkommen.
quelle
Uncaught SecurityError: Blocked a frame with origin "http://foo.bar.com" from accessing a frame with origin "null". The frame requesting access has a protocol of "http", the frame being accessed has a protocol of "data". Protocols must match.
@ResourceMapping() public void downloadFile(final ResourceRequest request, final ResourceResponse response, @ModelAttribute("downForm") FormModel model)
aber es funktioniert nicht ..Hier ist was ich getan habe, reines Javascript und HTML. Habe es nicht getestet, aber das sollte in allen Browsern funktionieren.
quelle
quelle
download
Attribut nicht, sodass Ihre Datei den Namen "Unbekannt" trägtIn Rails mache ich das so:
Der Trick ist der window.location- Teil. Die Methode des Controllers sieht folgendermaßen aus:
quelle
Verwenden
window.open
https://developer.mozilla.org/en-US/docs/Web/API/Window/openSie können diese Codezeile beispielsweise in einen Klick-Handler einfügen:
Es wird eine neue Registerkarte geöffnet (aufgrund des Fensternamens '_blank') und auf dieser Registerkarte wird die URL geöffnet.
Ihr serverseitiger Code sollte auch Folgendes haben:
Auf diese Weise sollte der Browser den Benutzer auffordern, die Datei auf der Festplatte zu speichern, anstatt ihnen nur die Datei anzuzeigen. Außerdem wird die gerade geöffnete Registerkarte automatisch geschlossen.
quelle
Ich versuche, eine CSV-Datei herunterzuladen und dann etwas zu tun, nachdem der Download abgeschlossen ist. Ich muss also eine entsprechende
callback
Funktion implementieren .Die Verwendung
window.location="..."
ist keine gute Idee, da ich das Programm nach Abschluss des Downloads nicht mehr bedienen kann. So etwas ändern Sie den Header, so dass es keine gute Idee ist.fetch
ist eine gute Alternative , kann jedoch IE 11 nicht unterstützen . Undwindow.URL.createObjectURL
nicht unterstützen kann IE 11.You beziehen kann dies .Dies ist mein Code, er ähnelt dem Code von Shahrukh Alam. Sie sollten jedoch darauf achten, dass
window.URL.createObjectURL
möglicherweise Speicherlecks auftreten. Sie können beziehen sich diese . Wenn die Antwort eingegangen ist, werden die Daten im Speicher des Browsers gespeichert. Bevor Sie auf dena
Link klicken , wurde die Datei heruntergeladen. Dies bedeutet, dass Sie nach dem Download alles tun können.quelle
So laden Sie eine Datei herunter, nachdem Sie sie von AJAX erhalten haben
Es ist praktisch, wenn die Datei für längere Zeit erstellt wurde und Sie PRELOADER anzeigen müssen
Beispiel beim Absenden eines Webformulars:
Die optionale Funktion ist auskommentiert, um das Beispiel zu vereinfachen.
Es müssen keine temporären Dateien auf dem Server erstellt werden.
Unter jQuery v2.2.4 OK. Bei der alten Version tritt ein Fehler auf:
quelle
filename.match(/filename=(.*)/)[1]
(ohne doppelte Anführungszeichen oder Fragezeichen) - regex101.com/r/2AsD4y/2 . Ihre Lösung war jedoch die einzige Lösung, die nach langem Suchen funktioniert hat.Hinzufügen einiger weiterer Dinge zur obigen Antwort zum Herunterladen einer Datei
Unten finden Sie einen Java-Spring-Code, der ein Byte-Array generiert
Jetzt können Sie im Javascript-Code mit FileSaver.js eine Datei mit dem folgenden Code herunterladen
Das obige wird Datei herunterladen
quelle
Ok, hier ist der Arbeitscode für die Verwendung von MVC und Sie erhalten Ihre Datei von einem Controller
Nehmen wir an, Sie müssen Ihr Byte-Array deklarieren und füllen. Sie müssen lediglich die Datei-Funktion verwenden (mit System.Web.Mvc).
und fügen Sie dann in derselben Steuerung diese 2 Funktionen hinzu
und dann können Sie Ihren Controller anrufen, um den Rückruf "Erfolg" oder "Fehler" herunterzuladen und zu erhalten
quelle
Ich habe einen Fix gefunden, der es Ihnen ermöglicht, einen Javascript-Aufruf zu verwenden, um den Download anzufordern und dann einen Rückruf zu erhalten, wenn der Download tatsächlich startet. Ich fand dies hilfreich, wenn der Link ein serverseitiges Skript ausführt, das ein wenig Zeit benötigt, um die Datei vor dem Senden zu erstellen. Sie können sie also darauf hinweisen, dass sie verarbeitet werden. Wenn die Datei dann endgültig gesendet wird, entfernen Sie diese Verarbeitungsbenachrichtigung. Aus diesem Grund wollte ich zunächst versuchen, die Datei über Ajax zu laden, damit ein Ereignis auftreten kann, wenn die Datei angefordert wird, und ein anderes, wenn der Download tatsächlich beginnt.
das js auf der Titelseite
der iframe
dann die andere Datei:
Ich denke, es gibt eine Möglichkeit, Get-Daten mit js zu lesen, sodass dann kein PHP benötigt wird. aber ich weiß es nicht sofort und der Server, den ich benutze, unterstützt PHP, so dass dies für mich funktioniert. dachte, ich würde es teilen, falls es jemandem hilft.
quelle
Wenn Sie jQuery File Download verwenden möchten, beachten Sie dies bitte für IE. Sie müssen die Antwort zurücksetzen, sonst wird sie nicht heruntergeladen
Ihre Aktion kann
ServletResponseAware
für den Zugriff implementiert werdengetServletResponse()
quelle
Es ist sicher, dass Sie dies nicht über einen Ajax-Anruf tun können.
Es gibt jedoch eine Problemumgehung.
Schritte :
Wenn Sie form.submit () zum Herunterladen der Datei verwenden, können Sie Folgendes tun:
Dies ist hilfreich, wenn Sie entscheiden möchten, ob die Datei nach dem Erstellen von form.submit () heruntergeladen werden muss oder nicht. Beispiel: Es kann vorkommen, dass auf form.submit () eine Ausnahme auf der Serverseite auftritt und stattdessen Nach einem Absturz müssen Sie möglicherweise eine benutzerdefinierte Nachricht auf der Clientseite anzeigen. In diesem Fall kann diese Implementierung hilfreich sein.
quelle
Es gibt eine andere Lösung zum Herunterladen einer Webseite in Ajax. Ich beziehe mich jedoch auf eine Seite, die zuerst verarbeitet und dann heruntergeladen werden muss.
Zuerst müssen Sie die Seitenverarbeitung vom Ergebnisdownload trennen.
1) Im Ajax-Aufruf werden nur die Seitenberechnungen durchgeführt.
Ich hoffe, diese Lösung kann für viele nützlich sein, so wie es für mich war.
quelle
quelle
Das ist, dass es in jedem Browser so gut funktioniert (ich verwende asp.net core)
quelle
Ich hatte lange mit diesem Problem zu kämpfen. Schließlich half mir eine elegante externe Bibliothek, die hier vorgeschlagen wurde.
quelle