486 Stimmen

Datei-Download von Ajax-Post verarbeiten

Ich habe eine JavaScript-App, die Ajax POST-Anforderungen an eine bestimmte URL sendet. Die Antwort kann ein JSON-String sein oder es kann sich um eine Datei handeln (als Anhang). Ich kann problemlos Content-Type und Content-Disposition in meinem Ajax-Aufruf erkennen, aber sobald ich feststelle, dass die Antwort eine Datei enthält, wie kann ich dem Client anbieten, sie herunterzuladen? Ich habe eine Reihe ähnlicher Threads hier gelesen, aber keiner von ihnen liefert die Antwort, nach der ich suche.

Bitte, bitte, bitte posten Sie keine Antworten, die vorschlagen, dass ich Ajax nicht verwenden sollte oder den Browser umleiten sollte, denn das ist keine Option. Die Verwendung eines einfachen HTML-Formulars ist ebenfalls keine Option. Was ich brauche, ist, dem Client einen Download-Dialog anzuzeigen. Kann dies gemacht werden und wie?

1voto

Armando Punkte 940

Ich habe dieses FileSaver.js benutzt. In meinem Fall mit CSV-Dateien habe ich dies gemacht (in Coffeescript):

  $.ajax
    url: "url-zum-server"
    data: "daten-zum-sendenn"
    success: (csvDaten)->
      blob = new Blob([csvDaten], { type: 'text/csv' })
      saveAs(blob, "dateiname.csv")

Ich denke, für den kompliziertesten Fall müssen die Daten ordnungsgemäß verarbeitet werden. Unter der Haube implementiert FileSaver.js den gleichen Ansatz wie die Antwort von Jonathan Amend.

0voto

netluke Punkte 51

Es gibt eine andere Lösung, um eine Webseite in Ajax herunterzuladen. Aber ich beziehe mich auf eine Seite, die zuerst verarbeitet werden muss und dann heruntergeladen wird.

Zuerst müssen Sie die Seitenverarbeitung vom Ergebnisdownload trennen.

1) Nur die Seitenberechnungen werden im Ajax-Aufruf durchgeführt.

$.post("CalculusPage.php", { calculusFunction: true, ID: 29, data1: "a", data2: "b" },

       function(data, status) 
       {
            if (status == "success") 
            {
                /\* 2) In der Antwort wird die Seite heruntergeladen, die die vorherigen Berechnungen verwendet. Dies kann beispielsweise eine Seite sein, die die Ergebnisse einer Tabelle ausgibt, die im Ajax-Aufruf berechnet wurde. \*/
                window.location.href = DownloadPage.php+"?ID="+29;
            }               
       }
);

// Zum Beispiel: in der CalculusPage.php

    if ( !empty($\_POST\["calculusFunction"\]) ) 
    {
        $ID = $\_POST\["ID"\];

        $query = "INSERT INTO ExamplePage (data1, data2) VALUES ('".$\_POST\["data1"\]."', '".$\_POST\["data2"\]."') WHERE id = ".$ID;
        ...
    }

// Zum Beispiel: in der DownloadPage.php

    $ID = $\_GET\["ID"\];

    $sede = "SELECT \* FROM ExamplePage WHERE id = ".$ID;
    ...

    $filename="Export\_Data.xls";
    header("Content-Type: application/vnd.ms-excel");
    header("Content-Disposition: inline; filename=$filename");

    ...

Ich hoffe, diese Lösung kann für viele nützlich sein, so wie es für mich war.

0voto

Abhishek Sinha Punkte 5035

Wenn die Antwort ein Array-Puffer ist, versuchen Sie Folgendes im `onsuccess`-Event in Ajax:

 if (event.data instanceof ArrayBuffer) {
          var binary = '';
          var bytes = new Uint8Array(event.data);
          for (var i = 0; i < bytes.byteLength; i++) {
              binary += String.fromCharCode(bytes[i])
          }
          $("#some_id").append("");
          return;
      }
  • wo `event.data` die Antwort ist, die im Erfolgsfall der `xhr`-Ereignisfunktion empfangen wird.

0voto

fstrandner Punkte 9

Um Jonathan Amends Antwort für Edge zum Laufen zu bringen, habe ich folgende Änderungen vorgenommen:

var blob = typeof File === 'function'
    ? new File([this.response], filename, { type: type })
    : new Blob([this.response], { type: type });

zu diesem

var f = typeof File+"";
var blob = f === 'function' && Modernizr.fileapi
    ? new File([this.response], filename, { type: type })
    : new Blob([this.response], { type: type });

Ich hätte das lieber als Kommentar gepostet, aber ich habe nicht genug Reputation dafür

0voto

il0v3d0g Punkte 595

Ich benötigte eine ähnliche Lösung wie die von @alain-cruz, aber in nuxt/vue mit mehreren Downloads. Ich weiß, dass Browser mehrfache Dateidownloads blockieren, und ich habe auch eine API, die eine Gruppe von csv-formatierten Daten zurückgibt. Zuerst wollte ich JSZip verwenden, aber ich brauchte Unterstützung für IE, also hier ist meine Lösung. Wenn jemand mir helfen kann, dies zu verbessern, wäre das großartig, aber bisher funktioniert es für mich.

API gibt zurück:

data : {
  body: {
    fileOne: ""col1", "col2", "Datensatz1.1", "Datensatz1.2"... usw.",
    fileTwo: ""col1", "col2"..."
  }
}

page.vue:

export default = {
   data() {
     return {
       fileNames: ['fileOne', 'fileTwo'],
     }
   },
  computed: {
    ...mapState({
       fileOne: (state) => state.exportFile.fileOne,
       fileTwo: (state) => state.exportFile.fileTwo,
    }),
  },
  method: {
    handleExport() {
      //exportFileAction in store/exportFile needs to return promise
      this.$store.dispatch('exportFile/exportFileAction', paramsToSend)
        .then(async (response) => {
           const downloadPrep = this.fileNames.map(async (fileName) => {
           // using lodash to get computed data by the file name
           const currentData = await _.get(this, `${fileName}`);
           const currentFileName = fileName;
           return { currentData, currentFileName };
         });
         const response = await Promise.all(downloadPrep);
         return response;
       })
       .then(async (data) => {
         data.forEach(({ currentData, currentFileName }) => {
           this.forceFileDownload(currentData, currentFileName);
         });
       })
       .catch(console.error);
    },
    forceFileDownload(data, fileName) {
     const url = window.URL
         .createObjectURL(new Blob([data], { type: 'text/csv;charset=utf-8;' }));
     const link = document.createElement('a');
     link.href = url;
     link.setAttribute('download', `${fileName}.csv`);
     document.body.appendChild(link);
     link.click();
   },
}

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X