PHP Downloads realisieren

R

ReduX08

Foren As
Hi,
Ich mache mir gerade Gedanken wie man mit PHP am besten Downloads realisieren kann.

Bis jetzt kenne ich die Methode das man als erstes einen entsprechenden Header mit header() schickt und dann mit readfile es ausgibt.

Nur weiß ich nicht, gibt es da bei größeren files (<200MB) Probleme, wegen PHP Timeout?
Oder kann ich diese Methode getrost in meinem Script stehen lassen?

MFG ReduX08
 
PHP Timeouts kannste nicht unterbinden.
Was du allerdings machen kannst, ist ein header Location zum Download. So bleibt der Pfad zur Daten unbekannt, und es rennt ohne PHP. :)

PHP:
<?php header("Location: datei.rar"); ?>
 
Nur weiß ich nicht, gibt es da bei größeren files (<200MB) Probleme, wegen PHP Timeout?
Oder kann ich diese Methode getrost in meinem Script stehen lassen?

Bei einer normalen Konfiguration schafft PHP es auf 20 MB die Sekunde beim Einlesen. Beim Standard Timeout von 20 Sekunden kann die Datei also c.a. 400 MB groß sein. Je mehr Benutzer allerdings die Seite ansurfen desto weniger performant läuft PHP Ergo: Die lese Zeit und die maximal Dateigröße sinkt.

Allerdings glaube ich nicht, dass das PHP timeout bei readfile greift, da gibt es einige Exeptions. Teste es doch einfach mal mit einer größeren Datei.
 
Eine Datei per PHP auszuliefern ist so ziemlich das ineffizienteste was es gibt. Eine Alternative wäre lighttpd zu nutzen, da gibt es ein Modul für was nur einmal gültige Links generiert

EDIT: http://trac.lighttpd.net/trac/wiki/Docs:ModSecDownload

EDIT2: Meine erste Behauptung basiert nicht auf empirischen Daten, aber Apache und Lighttpd sollten ohne Probleme sowas performanter können
 
Zuletzt bearbeitet:
Hi,
Danke für eure Antworten.
Das Problem wird aber wohl sein, dass das script auch bei kollegen laufen soll und ich denen nicht vorschreiben kann was auf dem Server installiert werden muss.

Darf man an dieser Stelle vielleicht mal erfahren wie ihr es realisiert habt?
Oder nutzt ihr alle dieses Plugin.

P.S.: Wahschreinlich werde ich auf dieser Seite nie so große Files haben, aber man weiß ja nie was so kommt.

MFG ReduX08
 
Ja, wenn man an PHP gebunden ist, dann mache ich das so. Gegen Timeouts hilft nur Ausprobieren über gedrosselte Leitung z.B. und wenn nötig die Laufzeit für das Verzeichnis in dem das Skript liegt hochsetzen.
 
JavaScript

Hi!

Da man heute davon ausgehen kann, dass JavaScript im Browser aktiviert ist, könnte man (ich kenne ja nicht das komplette Skript) von PHP Javascript ausgeben lassen (wenns ein Datenbank-Ergebnis ist) oder es direkt in HTML schreiben. Wie fehleranfällig das ist, hab ich keine Einschätzung.
Man kann aber auf Download klicken und das Fenster zum Speichern öffnet sich und die Site bleibt immer noch geladen^^

In einen Button eingebettet heisst das:
Code:
<input type="button" value="Download" onclick="location.href='datei.rar'"/>

lg Baracuda

PS.: für Fortgeschrittene: man könnte es natürlich auch mit Ajax machen, einen Request an ein PHP-Skript mit Datenbank absenden, und dann die Datei laden lassen.
 
Also mal ehrlich. Die Frage des Threads wurde am 28.05.(!) bereits beantwortet und jetzt machst du den heute nochmal auf mit einer Lösung, die mit der Frage nichts zu tun hat?!

Es ist toll, dass du helfen möchtest und irgendwie muss man ja auch auf seine Threads kommen. Aber das kann man auch produktiver. (z.B. mit solchen Posts wie meinen ;-) ) Der TE wollte eine Datei mit PHP einlesen und übertragen. Das macht man normalerweise, wenn man verhindern will, dass die Dateien direkt heruntergeladen werden. Bsp.:
download.php?fileid=346535 liest aus der DB welche Datei 346535 auf der Platte ist, überprüft ob der User die Datei herunterladen darf und PHP liest dann die Datei ein und sendet sie. Die Datei liegt dann normalerweise ausserhalb des Verzeichnisses, wo das PHP Skript ist, so dass sie *nur* per Skript heruntergealden werden kann.

Übrigens die fortgeschrittene Version deines (sorry!) blödsinnigen Codebeispiels lautet
Code:
<a href="datei.rar">Linktext</a>
Man kann wenn man will auch nen Button an die Stelle setzen. Aber der größte Witz: Das funktioniert sogar mit dem IE4.0 und ganz ohne Java. Und auf der gleichen Seite bleibt man auch..
 
Berichtigung

Ich möchte mal ein paar Dinge richtigstellen.
Erstens möchte ich nicht nur auf eine sinnlose Anzahl von Threads kommen.
Zweitens:
Die mögliche Lösung der "fortgeschrittenen Lösung" (ich sehe ein es war vielleicht etwas überheblich) ist falsch.
Das zugehörige (ausbaufähige) Skript würde lauten:
Code:
var http_request = false;

function do_request(url) {
http_request = new XMLHttpRequest();

if(!http_request) {
alert("Keine xmlhttp-Instanz verfügbar!"),
exit;
}

http_request.onreadystatechange = download;
http_request.open('GET', url, true);
http_request.send(null);
}

function download() {
	if(http_request.readyState == 4) {
		if(http_request.status == 200) {
		location.href = http_request.responseText;
		}
		else {
		alert("Beim Request ist ein Fehler aufgetreten!");
		}
	}
}
So könnte etwas derartiges aussehen wenn man davon ausgeht dass vom PHP-Skript die Ziel-URL zurückgegeben wird.
Und ich bin noch nicht fertig. Es ist kein Java. Du bist ein Opfer der Namensähnlichkeit von Java und JavaScript. Java benötigt die jeweilige Runtime auf dem PC und würde als Applet geladen, was mit zunehmender Größe auch länger dauert. JavaScript hingegegen hat zwar ein syntaktische Ähnlichkeit zu Java, ist aber vollständig im Browser implementiert, kann daher auch nicht als eigenständige Applikation laufen und wird von fast jeder Website benutzt.
Noch ein wichtiger Unterschied: Java = Programmiersprache, JavaScript = Skriptsprache

lg

@saeckereier: falls du noch irgendwelche Differenzen mit mir haben solltest, bitte schreib mir eine pm, der Thread ist für sowas der falsche Ort.
 
Ich möchte mal ein paar Dinge richtigstellen.
Erstens möchte ich nicht nur auf eine sinnlose Anzahl von Threads kommen.
Zweitens: Die mögliche Lösung der "fortgeschrittenen Lösung" (ich sehe ein es war vielleicht etwas überheblich) ist falsch.
Das zugehörige (ausbaufähige) Skript würde lauten:
Code:
    [...]
So könnte etwas derartiges aussehen wenn man davon ausgeht dass vom PHP-Skript die Ziel-URL zurückgegeben wird.

Hallo barracuda. Ich geb zu, mein sehr ironischer Post macht es u.U. etwas schwer den Kernpunkt herauszulesen. Der Smiley sollte die Ironie andeuten, ich wollte dir nicht wirklich unterstellen, deine Postanzahl hochzutreiben, denn dafür hast du dir im Post viel zuviel Mühe gegeben. Aber der Kernpunkt des ganzen ist, dass deine Lösung mit der Frage nichts zu tun hat.

Worum es ging:
Eine Lösung, wie eine Datei, die außerhalb des Webroots liegt und somit auch nicht vom Webserver ausgelifert werden kann, mittels PHP gelesen und übertragen werden kann. Könnte die Datei per Webserver ausgeliefert werden, könnte jeder diese Datei herunterladen. Eine Überprüfung des Users wäre nicht möglich (HTTP AUTH ausgenommen, aber wenn schon eine Session existiert, wozu sollte man dann den User noch einmal authentifizieren). Der tradierte Weg dazu ist folgender:
  • Das PHP Skript öffnet die Datei, es kann ohne Problem jede Datei auf dem Rechner öffnen, deren Rechte entsprechend gesetzt sind. Meinetwegen /tmp/korinthe (Über den Webserver kann man nicht an diese Datei, denn der Webroot sei /srv/www/htdocs, dies ist beabsichtigt)
  • Das PHP Skript checkt irgendwie ob der Download erlaubt sein soll (Session Management, IP, Die Sekunden der aktuellen Zeit sind eine Primzahl oder was auch immer)
  • Falls der Download erlaubt ist, manipuliert das PHP Skript den Header der Response und setzt unter anderem Content-type (z.B. auf application/pdf )
  • Das PHP Skript öffnet die Datei /tmp/korinthe, liest sie ein und gibt sie als Response aus
  • Der Browser fragt wie üblich ob er speichern soll, öffnet die Datei oder was auch immer

Was du beschrieben hast:
Einen Weg, wie mittels JavaScript* ein Klick auf einen Button bewirkt, dass der location.href auf eine URL des Webservers gesetzt wird. Der Browser würde dasselbe tun, als wenn man diese Adresse in die Adressleiste eingetippt, er würde also den Webbrowser nach der Datei /tmp/korinthe fragen. Der Webbrowser kann dann nur versuchen /srv/www/htdocs/tmp/korinthe auszuliefern die nicht existiert, das Resultat: 404.

Das Problem: Deine Lösung lässt sich, und das ist eigentlich das traurige daran komplett ohne JavaScript schreiben und ist damit laut SelfHTML seit HTML 2.0 auf jedem Browser, egal wie eingestellt nutzbar:
Code:
<html>
    <head />
    <!-- Barracuda -->
    <input type="button" value="Download" onclick="location.href='http://www.google.de'"/>
    <!-- saeckereier, wenn es ein Button sein muss -->
    <form method="GET" action="http://www.google.de">
        <input type="submit" value="Download">
    </form>
    <!-- saeckereier Wenn man auch das Bild eines Buttons nehmen darf. Das kann man dann noch per CSS schön mit Mouse-Over ausstatten -->
    <a href="http://www.google.de">Google</a>
</html>

Obenstehender Code ist auf Firefox, Konqueror und Internet Explorer getestet. Laufen wird er auch auf allen anderen. Das schärfste: Der Internet Explorer 6 hat bei mir das Beispiel mit JavaScript blockiert, weil er das als gefährlichen Content einstuft. Das zweite Beispiel mit dem form läuft trotzdem.

Ich hoffe, dass du dir die Mühe gemacht hast, bis hier zu lesen. Ich habe sie mir gemacht, bis hier zu schreiben damit jemand, der in Zukunft den Thread ausgräbt die Unterschiede sehen kann. Ich habe mich nach reiflicher Überlegung entschlossen, doch hier zu posten.

Ich habe das AJAX Beispiel nicht mehr umgesetzt, aber mir trotzdem die Mühe gemacht es mir anzuschauen. Und ich gebe zu, dass das ein sehr kreativer Weg ist um einen Link zu generieren, trotzdem erfüllt ein <a> Tag denselben Zweck. Da die Seite mit diesem Skript ohnehin per PHP ausgegeben würde, könnte man statt AJAX gleich den fertigen Link mit reinschreiben. Denn es geht nicht darum, wohin der Link zeigt, sondern darum, dass PHP die Datei ausliefern muss, weil es der Webserver nicht kann.

Über ein Feedback per PN würde ich mich ehrlich freuen.

* Stimmt, ich habe mich vertippt, habe es noch gesehen und beschlossen es nicht zu editieren, weil es nicht relevant ist ob man nun JavaScript braucht oder Java oder sonst etwas. Glaub mir bitte, dass ich den Unterschied kenne.
 

Ähnliche Themen

Squid nur zum maskieren der eigenen IP, nicht für Webserver auf port 80

Samba (htpasswd Verschlüsselungsverfahren)

Internal Server Error :(

Apache zu langsam ?

[Debian - rcon] Azureus gibt Fehlermeldungen trotz installiertem Java

Zurück
Oben