Ich habe eine Javascript-App, die Ajax-POST-Anfragen an eine bestimmte URL sendet. Die Antwort kann eine JSON-Zeichenfolge oder eine Datei (als Anhang) sein. Ich kann den Inhaltstyp und die Inhaltsdisposition in meinem Ajax-Aufruf leicht erkennen. Wenn ich jedoch feststelle, dass die Antwort eine Datei enthält, wie biete ich dem Client an, sie herunterzuladen? Ich habe hier eine Reihe ähnlicher Themen gelesen, aber keine liefert die Antwort, nach der ich suche.
Bitte, bitte, bitte poste keine Antworten, die darauf hindeuten, dass ich Ajax dafür nicht verwenden oder den Browser umleiten sollte, da nichts davon eine Option ist. Die Verwendung eines einfachen HTML-Formulars ist ebenfalls keine Option. Ich muss dem Client einen Download-Dialog anzeigen. Kann das gemacht werden und wie?
quelle
Antworten:
Erstellen Sie ein Formular, verwenden Sie die POST-Methode, senden Sie das Formular ab - es ist kein Iframe erforderlich. Wenn die Serverseite auf die Anfrage antwortet, schreiben Sie einen Antwortheader für den MIME-Typ der Datei. Daraufhin wird ein Download-Dialog angezeigt. Ich habe dies einige Male getan.
Sie möchten eine inhaltliche Anwendung / einen inhaltlichen Download - suchen Sie einfach, wie Sie einen Download für die von Ihnen verwendete Sprache bereitstellen können.
quelle
Geben Sie nicht so schnell auf, da dies (in modernen Browsern) mit Teilen der FileAPI möglich ist:
Hier ist die alte Version mit jQuery.ajax. Es kann Binärdaten beschädigen, wenn die Antwort in eine Zeichenfolge mit einem Zeichensatz konvertiert wird.
quelle
document.body.removeChild(a);
var blob =this.responce; /** if (typeof File === 'function') { try { blob = new File([this.response], filename, { type: type }); } catch (e) { /* Edge */ } } if (typeof blob === 'undefined') { blob = new Blob([this.response], { type: type }); } */
window.location.href = downloadUrl
stattwindow.location = downloadUrl
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
Welche serverseitige Sprache verwenden Sie? In meiner App kann ich einfach eine Datei von einem AJAX-Aufruf herunterladen, indem ich die richtigen Header in der Antwort von PHP setze:
Header serverseitig einstellen
Dadurch wird der Browser zwar auf diese Download-Seite umgeleitet, aber wie @ahren bereits in seinem Kommentar sagte, wird er nicht von der aktuellen Seite weg navigieren.
Es geht darum, die richtigen Header festzulegen, damit Sie sicher eine geeignete Lösung für die von Ihnen verwendete serverseitige Sprache finden, wenn es sich nicht um PHP handelt.
Umgang mit der Antwortclientseite
Angenommen, Sie wissen bereits, wie ein AJAX-Aufruf getätigt wird, führen Sie auf der Clientseite eine AJAX-Anforderung an den Server aus. Der Server generiert dann einen Link, von dem diese Datei heruntergeladen werden kann, z. B. die Weiterleitungs-URL, auf die Sie verweisen möchten. Der Server antwortet beispielsweise mit:
Bei der Verarbeitung der Antwort fügen Sie eine
iframe
in Ihren Körper ein und setzen deniframe
SRC des S auf die URL, die Sie gerade so erhalten haben (zur Vereinfachung dieses Beispiels verwenden Sie jQuery):Wenn Sie die richtigen Header wie oben gezeigt festgelegt haben, erzwingt der Iframe einen Download-Dialog, ohne den Browser von der aktuellen Seite weg zu navigieren.
Hinweis
Zusätzlicher Zusatz in Bezug auf Ihre Frage; Ich denke, es ist am besten, JSON immer zurückzugeben, wenn Sie Dinge mit AJAX-Technologie anfordern. Nachdem Sie die JSON-Antwort erhalten haben, können Sie clientseitig entscheiden, was damit geschehen soll. Vielleicht möchten Sie beispielsweise später, dass der Benutzer auf einen Download-Link zur URL klickt, anstatt den Download direkt zu erzwingen. In Ihrem aktuellen Setup müssten Sie dazu sowohl die Client- als auch die Serverseite aktualisieren.
quelle
Für diejenigen, die eine Lösung aus einer Winkelperspektive suchen, hat dies für mich funktioniert:
quelle
link.download = ""
führt zu einem zufälligen Guid-Dateinamen undlink.download = null
zu einer Datei mit dem Namen "null".INPUT
Elements aufzeichnenHTMLInputElement.files
. Weitere Informationen finden Sie in den MDN-Dokumenten zur Dateieingabe .Hier ist, wie ich das zum Laufen gebracht habe: https://stackoverflow.com/a/27563953/2845977
Aktualisierte Antwort mit download.js
quelle
success: function (response, status, request) { download(response, "filename.txt", "application/text"); }
Ich sehe, dass Sie bereits eine Lösung gefunden haben, aber ich wollte nur einige Informationen hinzufügen, die jemandem helfen können, mit großen POST-Anfragen dasselbe zu erreichen.
Ich hatte das gleiche Problem vor ein paar Wochen, tatsächlich ist es nicht möglich, einen "sauberen" Download über AJAX zu erreichen. Die Filament Group hat ein jQuery-Plugin erstellt, das genau so funktioniert, wie Sie es bereits herausgefunden haben. Es heißt jQuery File Download hat jedoch einen Nachteil dieser Technik.
Wenn Sie große Anfragen über AJAX senden (z. B. Dateien + 1 MB), wirkt sich dies negativ auf die Reaktionsfähigkeit aus. Bei langsamen Internetverbindungen müssen Sie viel warten, bis die Anforderung gesendet wird, und auch warten, bis die Datei heruntergeladen wurde. Es ist nicht wie ein sofortiger "Klick" => "Popup" => "Download-Start". Es ist eher wie "Klicken" => "Warten, bis Daten gesendet werden" => "Warten auf Antwort" => "Download-Start", wodurch die Datei doppelt so groß erscheint, da Sie auf das Senden der Anforderung warten müssen über AJAX und erhalten Sie es als herunterladbare Datei zurück.
Wenn Sie mit kleinen Dateigrößen <1 MB arbeiten, werden Sie dies nicht bemerken. Aber wie ich in meiner eigenen App festgestellt habe, ist es für größere Dateien fast unerträglich.
Mit meiner App können Benutzer dynamisch generierte Bilder exportieren. Diese Bilder werden über POST-Anforderungen im Base64-Format an den Server gesendet (dies ist der einzig mögliche Weg), dann verarbeitet und in Form von PNG-, JPG-Dateien und Base64 an Benutzer zurückgesendet Zeichenfolgen für Bilder + 1 MB sind sehr groß. Dadurch müssen Benutzer mehr als nötig warten, bis die Datei heruntergeladen wird. Bei langsamen Internetverbindungen kann es sehr ärgerlich sein.
Meine Lösung hierfür bestand darin, die Datei vorübergehend auf den Server zu schreiben, sobald sie fertig ist, dynamisch einen Link zur Datei in Form einer Schaltfläche zu generieren, die zwischen den Zuständen "Bitte warten ..." und "Herunterladen" wechselt Drucken Sie das base64-Bild in einem Vorschau-Popup-Fenster aus, damit Benutzer mit der rechten Maustaste darauf klicken und es speichern können. Dies macht die Wartezeit für Benutzer erträglicher und beschleunigt die Arbeit.
Update 30. September 2014:
Beispiel für ein Download-Skript:
Ich weiß, dass dies weit über das hinausgeht, was das OP verlangt hat, aber ich hielt es für gut, meine Antwort mit meinen Ergebnissen zu aktualisieren. Als ich nach Lösungen für mein Problem suchte, las ich viele "Download from AJAX POST data" -Threads, die mir nicht die gesuchte Antwort gaben. Ich hoffe, diese Informationen helfen jemandem, der so etwas erreichen möchte.
quelle
jQuery File Download
einzige leitet mich zur URL weiter. Ich nenne es so :jQuery.download("api/ide/download-this-file.php", {filePath: path2Down}, "POST");
.Ich möchte auf einige Schwierigkeiten hinweisen, die bei der Verwendung der Technik in der akzeptierten Antwort auftreten, dh bei der Verwendung eines Formularposts:
Sie können keine Header für die Anforderung festlegen. Wenn Ihr Authentifizierungsschema Header enthält, ein Json-Web-Token, das im Authorization-Header übergeben wird, müssen Sie eine andere Möglichkeit zum Senden finden, z. B. als Abfrageparameter.
Sie können nicht wirklich sagen, wann die Anfrage abgeschlossen ist. Nun, Sie können ein Cookie verwenden, das bei der Antwort gesetzt wird, wie es von jquery.fileDownload ausgeführt wird , aber es ist bei weitem nicht perfekt. Es funktioniert nicht für gleichzeitige Anforderungen und wird unterbrochen, wenn eine Antwort nie eintrifft.
Wenn der Server mit einem Fehler antwortet, wird der Benutzer zur Fehlerseite weitergeleitet.
Sie können nur die von einem Formular unterstützten Inhaltstypen verwenden . Das heißt, Sie können JSON nicht verwenden.
Am Ende habe ich die Methode zum Speichern der Datei in S3 und zum Senden einer vorsignierten URL verwendet, um die Datei abzurufen.
quelle
Für diejenigen, die einen moderneren Ansatz suchen, können Sie die verwenden
fetch API
. Das folgende Beispiel zeigt, wie Sie eine Tabellenkalkulationsdatei herunterladen. Mit dem folgenden Code ist dies problemlos möglich.Ich glaube, dieser Ansatz ist viel einfacher zu verstehen als andere
XMLHttpRequest
Lösungen. Außerdem hat es eine ähnliche Syntax wie derjQuery
Ansatz, ohne dass zusätzliche Bibliotheken hinzugefügt werden müssen.Natürlich würde ich empfehlen, zu überprüfen, in welchem Browser Sie entwickeln, da dieser neue Ansatz im IE nicht funktioniert. Die vollständige Browserkompatibilitätsliste finden Sie unter folgendem [Link] [1].
Wichtig : In diesem Beispiel sende ich eine JSON-Anfrage an einen Server, der die angegebene Funktion abhört
url
. Dieseurl
muss festgelegt werden. In meinem Beispiel gehe ich davon aus, dass Sie diesen Teil kennen. Berücksichtigen Sie auch die Header, die für die Ausführung Ihrer Anforderung erforderlich sind. Da ich einen JSON sende, muss ich denContent-Type
Header hinzufügen und auf setzenapplication/json; charset=utf-8
, um dem Server den Typ der Anforderung mitzuteilen, die er erhalten wird.quelle
Hier ist meine Lösung mit einem temporären versteckten Formular.
Beachten Sie, dass ich JQuery massiv verwende, aber Sie können dasselbe mit nativem JS tun.
quelle
Wie bereits erwähnt, können Sie ein Formular zum Herunterladen über eine POST-Anfrage erstellen und senden. Sie müssen dies jedoch nicht manuell tun.
Eine wirklich einfache Bibliothek, um genau dies zu tun, ist jquery.redirect . Es bietet eine API ähnlich der Standardmethode
jQuery.post
:quelle
Dies ist eine 3 Jahre alte Frage, aber ich hatte heute das gleiche Problem. Ich habe nach Ihrer bearbeiteten Lösung gesucht, aber ich denke, dass sie die Leistung beeinträchtigen kann, da eine doppelte Anfrage gestellt werden muss. Wenn also jemand eine andere Lösung benötigt, bei der der Dienst nicht zweimal aufgerufen werden muss, habe ich dies folgendermaßen getan:
Dieses Formular wird nur verwendet, um den Dienst aufzurufen und die Verwendung von window.location () zu vermeiden. Danach müssen Sie nur noch ein Formular von jquery senden, um den Dienst aufzurufen und die Datei abzurufen. Es ist ziemlich einfach, aber auf diese Weise können Sie einen Download mit einem POST durchführen . Ich weiß jetzt, dass dies einfacher sein könnte, wenn der Dienst, den Sie anrufen, ein GET ist , aber das ist nicht mein Fall.
quelle
Ich habe diese FileSaver.js verwendet . In meinem Fall mit CSV-Dateien habe ich dies getan (in Coffescript):
Ich denke, für den kompliziertesten Fall müssen die Daten ordnungsgemäß verarbeitet werden. Unter der Haube implementieren FileSaver.js den gleichen Ansatz wie die Antwort von Jonathan Amend .
quelle
Siehe: http://www.henryalgus.com/reading-binary-files-using-jquery-ajax/ Es wird ein Blob als Antwort zurückgegeben, der dann in den Dateispeicher eingefügt werden kann
quelle
Um Jonathan Amends Antwort auf die Arbeit in Edge zu erhalten, habe ich die folgenden Änderungen vorgenommen:
dazu
Ich hätte dies lieber als Kommentar gepostet, aber dafür habe ich nicht genug Ruf
quelle
Hier ist meine Lösung aus verschiedenen Quellen: Serverseitige Implementierung:
Clientseitige Implementierung (mit jquery):
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
Wenn die Antwort ein Array-Puffer ist , versuchen Sie dies unter onsuccess-Ereignis in Ajax:
quelle
Unten ist meine Lösung zum Herunterladen mehrerer Dateien in Abhängigkeit von einer Liste, die aus einigen IDs besteht, und zum Nachschlagen in der Datenbank. Die Dateien werden ermittelt und können heruntergeladen werden - sofern vorhanden. Ich rufe die C # MVC-Aktion für jede Datei mit Ajax auf.
Und ja, wie andere sagten, ist es möglich, dies in jQuery Ajax zu tun. Ich habe es mit Ajax-Erfolg gemacht und sende immer die Antwort 200.
Das ist also der Schlüssel:
Und das ist mein Code:
Dann rufen Sie an:
C # MVC:
Solange Sie die Antwort 200 zurückgeben, kann der Erfolg in Ajax damit funktionieren. Sie können überprüfen, ob die Datei tatsächlich vorhanden ist oder nicht, da die folgende Zeile in diesem Fall falsch wäre, und Sie können den Benutzer darüber informieren:
quelle
Ich brauchte eine ähnliche Lösung wie @ alain-cruz, aber in nuxt / vue mit mehreren Downloads. Ich weiß, dass Browser mehrere Dateidownloads blockieren, und ich habe auch eine API, die eine Reihe von CSV-formatierten Daten zurückgibt. Ich wollte zuerst JSZip verwenden, brauchte aber IE-Unterstützung. Hier ist meine Lösung. Wenn mir jemand helfen kann, das zu verbessern, wäre das großartig, aber es funktioniert bisher für mich.
API gibt zurück:
page.vue:
quelle