it-swarm.com.de

Dateidownload mit JavaScript starten

Nehmen wir an, ich habe Download-Links für Dateien auf meiner Site.

Wenn Sie auf diese Links klicken, senden Sie eine AJAX) - Anfrage an den Server, der die URL mit dem Speicherort der Datei zurückgibt.

Ich möchte den Browser anweisen, die Datei herunterzuladen, wenn die Antwort zurückkommt. Gibt es eine tragbare Möglichkeit, dies zu tun?

54
Vasil

Probieren Sie diese Bibliothek aus https://github.com/PixelsCommander/Download-File-JS Sie ist moderner als alle zuvor beschriebenen Lösungen, da sie das Attribut "Download" und eine Kombination von Methoden verwendet, um die bestmögliche Erfahrung zu erzielen .

Hier erklärt - http://pixelscommander.com/en/javascript/javascript-file-downliading-ignore-content-type/

Scheint das ideale Stück Code zu sein, um den Download in JavaScript zu starten.

4
PixelCommander

Wir machen es so: Fügen Sie zuerst dieses Skript hinzu.

<script type="text/javascript">
function populateIframe(id,path) 
{
    var ifrm = document.getElementById(id);
    ifrm.src = "download.php?path="+path;
}
</script>

Platzieren Sie dies an der Stelle, an der Sie den Download-Button haben möchten (hier verwenden wir nur einen Link):

<iframe id="frame1" style="display:none"></iframe>
<a href="javascript:populateIframe('frame1','<?php echo $path; ?>')">download</a>

Die Datei 'download.php' (muss auf Ihren Server gestellt werden) enthält einfach:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

Wenn Sie also auf den Link klicken, ruft der versteckte Iframe die Quelldatei 'download.php' ab bzw. öffnet sie. Mit dem Pfad als get-Parameter. Wir finden das die beste Lösung!

Es ist zu beachten, dass der PHP Teil dieser Lösung eine einfache Demonstration und möglicherweise sehr, sehr unsicher ist. Er ermöglicht dem Benutzer das Herunterladen einer beliebigen Datei, nicht nur eines vordefinierten Satzes. Das bedeutet Sie könnten Teile des Quellcodes der Site selbst herunterladen, möglicherweise API-Anmeldeinformationen usw. enthalten.

24
roulio

Ich habe ein Open Source jQuery File Download Plugin ( Demo mit Beispielen ) ( GitHub ) erstellt, das auch in Ihrer Situation helfen könnte. Es funktioniert ziemlich ähnlich mit einem iframe, hat aber einige coole Funktionen, die ich sehr praktisch gefunden habe:

  • Der Benutzer verlässt nie dieselbe Seite, von der er einen Dateidownload initiiert hat. Diese Funktion wird für moderne Webanwendungen immer wichtiger
  • Getestete browserübergreifende Unterstützung (einschließlich mobiler!)
  • Es unterstützt POST und GET-Anforderungen auf ähnliche Weise wie die AJAX API von jQuery
  • mit den Funktionen successCallback und failCallback können Sie genau angeben, was der Benutzer in beiden Situationen sieht
  • In Verbindung mit der jQuery-Benutzeroberfläche kann ein Entwickler dem Benutzer auf einfache Weise mitteilen, dass ein Dateidownload stattfindet, das Modal auflösen, nachdem der Download gestartet wurde, oder den Benutzer auf freundliche Weise darüber informieren, dass ein Fehler aufgetreten ist. Ein Beispiel hierfür finden Sie in der Demo.
18
John Culviner

Lesen der Antworten - einschließlich der akzeptierten - Ich möchte auf die Sicherheitsaspekte hinweisen, die sich aus der Übergabe eines Pfads direkt zu readfile über GET ergeben.

Für manche mag es offensichtlich erscheinen, aber manche können diesen Code einfach kopieren/einfügen:

<?php 
   header("Content-Type: application/octet-stream");
   header("Content-Disposition: attachment; filename=".$_GET['path']);
   readfile($_GET['path']);
?>

Was passiert also, wenn ich diesem Skript etwas wie '/ path/to/fileWithSecrets' übergebe? Das angegebene Skript sendet jede Datei, auf die der Webserver-Benutzer Zugriff hat.

In dieser Diskussion erfahren Sie, wie Sie dies verhindern können: Wie stelle ich sicher, dass sich ein Dateipfad in einem bestimmten Unterverzeichnis befindet?

14
DanielKhan

Wenn dies Ihre eigene Serveranwendung ist, schlage ich vor, den folgenden Header zu verwenden

Content-disposition: attachment; filename=fname.ext

Dadurch wird jeder Browser gezwungen, die Datei herunterzuladen und nicht im Browserfenster zu rendern.

10
fasih.rana

Ruf einfach an window.location.href = new_url von Ihrem Javascript und es wird den Browser zu dieser URL umleiten, wie es der Benutzer in die Adressleiste eingegeben hatte

7
Gareth

Sie stimmen den von maxnk genannten Methoden zu, möchten jedoch möglicherweise erneut versuchen, den Browser automatisch zum Herunterladen der URL zu zwingen. Für Binärdateien funktioniert es möglicherweise einwandfrei, aber für andere Dateitypen (Text, PDF, Bilder, Video) möchte der Browser es möglicherweise im Fenster (oder IFRAME) rendern, anstatt es auf der Festplatte zu speichern.

Wenn Sie wirklich einen Ajax-Aufruf ausführen müssen, um die endgültigen Download-Links abzurufen, können Sie den Download-Link (aus der Ajax-Antwort) mithilfe von DHTML dynamisch in die Seite schreiben. Auf diese Weise kann der Benutzer entweder darauf klicken, um es herunterzuladen (wenn es sich um eine Binärdatei handelt) oder es in seinem Browser anzeigen - oder auf dem Link "Speichern unter" auswählen, um es auf der Festplatte zu speichern. Es ist ein zusätzlicher Klick, aber der Benutzer hat mehr Kontrolle.

3
Marc Novakowski

Um die Sicherheitslücke in der Antwort zu umgehen, die am häufigsten gewählt wurde, können Sie den iframe src direkt auf die gewünschte Datei setzen (anstelle einer Zwischen-PHP-Datei) und die Header-Informationen in einer .htaccess-Datei festlegen:

<Files *.apk>
     ForceType application/force-download
     Header set Content-Disposition attachment
     Header set Content-Type application/vnd.Android.package-archive
     Header set Content-Transfer-Encoding binary
</Files>
3
Matt K

In Bezug auf die Top-Antwort habe ich eine mögliche Lösung für das Sicherheitsrisiko.

<?php
     if(isset($_GET['path'])){
         if(in_array($_GET['path'], glob("*/*.*"))){
             header("Content-Type: application/octet-stream");
             header("Content-Disposition: attachment; filename=".$_GET['path']);
             readfile($_GET['path']);
         }
     }
?>

Mit der glob () - Funktion (ich habe die Download-Datei in einem Pfad getestet, der einen Ordner über der herunterzuladenden Datei liegt) konnte ich ein schnelles Array von Dateien erstellen, die "heruntergeladen" werden dürfen, und den übergebenen Pfad daraufhin überprüfen . Dies stellt nicht nur sicher, dass die erfasste Datei nicht sensibel ist, sondern überprüft gleichzeitig auch die Existenz der Dateien.

~ Hinweis: Javascript/HTML ~

HTML:

<iframe id="download" style="display:none"></iframe>

und

<input type="submit" value="Download" onclick="ChangeSource('document_path');return false;">

JavaScript:

<script type="text/javascript">
    <!--
        function ChangeSource(path){
            document.getElementByID('download').src = 'path_to_php?path=' + document_path;
        }
    -->
</script>
2

Ich schlage vor, einen unsichtbaren Iframe auf der Seite zu erstellen und src auf die URL einzustellen, die Sie vom Server erhalten haben. Der Download startet ohne erneutes Laden der Seite.

Oder setzen Sie einfach die aktuelle document.location.href auf die empfangene URL-Adresse. Dies kann jedoch dazu führen, dass der Benutzer einen Fehler sieht, wenn das angeforderte Dokument tatsächlich nicht vorhanden ist.

2
maxnk

Warum machen Sie serverseitige Dinge, wenn Sie nur den Browser auf eine andere window.location.href umleiten müssen?

Hier ist Code, der? File = QueryString ( aus dieser Frage entnommen ) analysiert und den Benutzer in 1 Sekunde zu dieser Adresse umleitet (funktioniert bei mir sogar mit Android Browser):

<script type="text/javascript">
    var urlParams;
    (window.onpopstate = function () {
        var match,
        pl = /\+/g,  // Regex for replacing addition symbol with a space
        search = /([^&=]+)=?([^&]*)/g,
        decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
        query = window.location.search.substring(1);

        urlParams = {};
        while (match = search.exec(query))
            urlParams[decode(match[1])] = decode(match[2]);
    })();

    (window.onload = function() {
        var path = urlParams["file"];
        setTimeout(function() { document.location.href = path; }, 1000);
    });
</script>

Wenn Sie jQuery in Ihrem Projekt haben, entfernen Sie definitiv diese window.onpopstate- und window.onload-Handler und machen Sie alles in $ (document) .ready (function () {});

1
nikib3ro

Ich würde window.open() vorschlagen, um ein Popup-Fenster zu öffnen. Wenn es sich um einen Download handelt, wird kein Fenster angezeigt und Sie erhalten Ihre Datei. Wenn es einen 404 oder etwas gibt, wird der Benutzer ihn in einem neuen Fenster sehen (daher wird seine Arbeit nicht gestört, aber er erhält trotzdem eine Fehlermeldung).

1
Vilx-