it-swarm.com.de

herunterladen einer Datei mit einer Ajax-Anforderung

Ich möchte eine "Ajax-Download-Anfrage" senden, wenn ich auf eine Schaltfläche klicke, also habe ich folgendes versucht:

javascript:

var xhr = new XMLHttpRequest();
xhr.open("GET", "download.php");
xhr.send();

download.php:

<?
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename= file.txt");
header("Content-Transfer-Encoding: binary");    
readfile("file.txt");
?>

funktioniert aber nicht wie erwartet, wie kann ich das tun? Danke im Voraus

74
Manuel Di Iorio

Update 27. April 2015

Auf dem Weg zur HTML5-Szene steht das download-Attribut . Es wird unterstützt in Firefox und Chrome und demnächst an IE11. Abhängig von Ihren Anforderungen können Sie sie anstelle einer Anforderung AJAX (oder mithilfe von window.location) verwenden, solange sich die zu ladende Datei im selben Ursprung befindet wie Ihre Site.

Sie können die Anforderung von AJAX/window.location immer als Fallback ausführen, indem Sie einige JavaScript verwenden, um zu testen, ob download unterstützt wird, und falls nicht, wechseln Sie zum Aufruf window.location.

Originalantwort

Sie können keine Anforderung für AJAX haben, um die Download-Eingabeaufforderung zu öffnen, da Sie physisch zu der Datei navigieren müssen, um zum Download aufzufordern. Stattdessen können Sie eine Erfolgsfunktion verwenden, um zur download.php zu navigieren. Dadurch wird die Download-Eingabeaufforderung geöffnet, die aktuelle Seite wird jedoch nicht geändert.

$.ajax({
    url: 'download.php',
    type: 'POST',
    success: function() {
        window.location = 'download.php';
    }
});

Obwohl dies die Frage beantwortet, ist es besser, window.location zu verwenden und die Anforderung AJAX vollständig zu vermeiden.

90
Steven Lambert

Dafür brauchst du eigentlich gar keinen Ajax. Wenn Sie nur "download.php" als href auf der Schaltfläche festgelegt haben oder wenn es sich nicht um einen Link handelt, verwenden Sie:

window.location = 'download.php';

Der Browser sollte den binären Download erkennen und nicht die aktuelle Seite laden, sondern die Datei nur als Download bereitstellen.

38
Jelle Kralt

Damit der Browser eine Datei herunterlädt, müssen Sie die Anforderung so stellen:

 function downloadFile(urlToSend) {
     var req = new XMLHttpRequest();
     req.open("GET", urlToSend, true);
     req.responseType = "blob";
     req.onload = function (event) {
         var blob = req.response;
         var fileName = req.getResponseHeader("fileName") //if you have the fileName header available
         var link=document.createElement('a');
         link.href=window.URL.createObjectURL(blob);
         link.download=fileName;
         link.click();
     };

     req.send();
 }
18
João Marcos

Es ist möglich. Sie können den Download von einer Ajax-Funktion aus starten, z. B. unmittelbar nachdem die CSV-Datei erstellt wurde.

Ich habe eine Ajax-Funktion, die eine Datenbank mit Kontakten in eine CSV-Datei exportiert. Sobald sie abgeschlossen ist, wird der CSV-Dateidownload automatisch gestartet. Nachdem ich also den responseText erhalten habe und alles in Ordnung ist, leite ich den Browser so um:

window.location="download.php?filename=export.csv";

Meine download.php -Datei sieht folgendermaßen aus:

<?php

    $file = $_GET['filename'];

    header("Cache-Control: public");
    header("Content-Description: File Transfer");
    header("Content-Disposition: attachment; filename=".$file."");
    header("Content-Transfer-Encoding: binary");
    header("Content-Type: binary/octet-stream");
    readfile($file);

?>

Es erfolgt keinerlei Aktualisierung der Seite, und die Datei wird automatisch heruntergeladen. 

NOTE- In folgenden Browsern getestet:

Chrome v37.0.2062.120 
Firefox v32.0.1
Opera v12.17
Internet Explorer v11
13
Pedro Sousa

Browserübergreifende Lösung, getestet auf Chrome, Firefox, Edge, IE11.

Fügen Sie im DOM ein Tag mit verborgenen Links hinzu:

<a id="target" style="display: none"></a>

Dann:

var req = new XMLHttpRequest();
req.open("GET", downloadUrl, true);
req.responseType = "blob";

req.onload = function (event) {
  var blob = req.response;
  var fileName = null;
  var contentType = req.getResponseHeader("content-type");

  // IE/Edge seems not returning some response header
  if (req.getResponseHeader("content-disposition")) {
    var contentDisposition = req.getResponseHeader("content-disposition");
    fileName = contentDisposition.substring(contentDisposition.indexOf("=")+1);
  } else {
    fileName = "unnamed." + contentType.substring(contentType.indexOf("/")+1);
  }

  if (window.navigator.msSaveOrOpenBlob) {
    // Internet Explorer
    window.navigator.msSaveOrOpenBlob(new Blob([blob], {type: contentType}), fileName);
  } else {
    var el = document.getElementById("target");
    el.href = window.URL.createObjectURL(blob);
    el.download = fileName;
    el.click();
  }
};
req.send();
9
leo

Ich bevorzuge location.assign(url);

Vollständiges Syntaxbeispiel:

document.location.assign('https://www.urltodocument.com/document.pdf');

developer.mozilla.org/en-US/docs/Web/API/Location.assign

2
Telmo Dias

Ihre Bedürfnisse werden durch window.location('download.php'); abgedeckt
Aber ich denke, dass Sie die herunterzuladende Datei übergeben müssen, nicht immer die gleiche Datei herunterladen, und deshalb verwenden Sie eine Anfrage. Eine Möglichkeit ist, eine PHP-Datei so einfach wie showfile.php und zu erstellen mache eine Anfrage wie

var myfile = filetodownload.txt
var url = "shofile.php?file=" + myfile ;
ajaxRequest.open("GET", url, true);

showfile.php

<?php
$file = $_GET["file"] 
echo $file;

dabei ist file der Dateiname, der über Get oder Post in der Anfrage übergeben wird und fängt dann die Antwort in einer Funktion einfach ab

if(ajaxRequest.readyState == 4){
                        var file = ajaxRequest.responseText;
                        window.location = 'downfile.php?file=' + file;  
                    }
                }
0
lisandro

Diese Lösung unterscheidet sich nicht sehr von der oben genannten, aber für mich funktioniert sie sehr gut und ich denke, dass sie sauber ist.

Ich empfehle, die Dateiserverseite (base64_encode (), wenn Sie PHP verwenden) mit base64 zu codieren und die base64-codierten Daten an den Client zu senden

Auf dem Client machen Sie folgendes:

 let blob = this.dataURItoBlob(THE_MIME_TYPE + "," + response.file);
 let uri = URL.createObjectURL(blob);
 let link = document.createElement("a");
 link.download = THE_FILE_NAME,
 link.href = uri;
 document.body.appendChild(link);
 link.click();
 document.body.removeChild(link);

Dieser Code fügt die verschlüsselten Daten in einen Link ein und simuliert einen Klick auf den Link und entfernt ihn dann.

0
Kapalua

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

Zuerst müssen Sie die Seitenverarbeitung vom Ergebnis-Download trennen.

1) Beim Ajax-Aufruf werden nur die Seitenberechnungen durchgeführt.

 $ .post ("CalculusPage.php", {calculusFunction: true, ID: 29, data1: "a", data2: "b"}, 
 
 Funktion (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 im Ajax-Aufruf berechneten Tabelle druckt. */
 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; Dateiname = $ Dateiname"); 
 
 ... 

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

0
netluke

Das Dekodieren eines Dateinamens aus dem Header ist etwas komplexer ...

    var filename = "default.pdf";
    var disposition = req.getResponseHeader('Content-Disposition');

    if (disposition && disposition.indexOf('attachment') !== -1) 
    {
       var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
       var matches = filenameRegex.exec(disposition);

       if (matches != null && matches[1]) 
           filename = matches[1].replace(/['"]/g, '');
    }
0
Lumic