basi: Generierung von Downloads: DNS-Problem?

Hi,
habe folgendes umgesetzt:

Ich habe Dateien auf dem Server liegen, die ich über ein php Skript zum Download anbiete (mehrere auf einer Seite). Das funktioniert auch.
Die Dateien sind alle als .dat gespeichert und werden beim Download mit dem richtigen Mimetype downgeloadet.
Jetzt tritt bei einigen Downloads das Problem auf, dass der Downloaddialog nicht erscheint:

Fehlermeldung im IE 5: "Die Seite kann nicht angezeigt werden. [...] Fehler: Server oder DNS kann nicht gefunden werden." Das ist die Seite dnserror.htm, die der IE ausspuckt.

Fehlermeldung im Netscape 7: "Das Dokument enthält keine Daten." (als alert-message, Fenster bleibt leer)

Dabei gibt es kein bestimmtes Muster, also es hängt nicht vom MimeType der Datei etc. ab, dass der Download nicht funzt.

Ich habe alle Variablen überprüft, mit denen der Pfad zur Datei generiert wird -> alles korrekt.
Ich habe die Dateien auf dem Server überprüft -> alle heil und ausführbar.
Das Skript scheint also i.O. zu sein. Die Dateien auch.

Hier nochmal der Auszug aus dem download-Skript. Die Variablen werden mit den jeweiligen Ergebnissen aus der DB gefüllt:

-$individuelMimeType ist der entsprechende Mimetype der Datei
-$name der vorgeschlagene Name für den Download,
-$physicalName ist der Name der Datei auf dem Server (also mit .dat als Endung).
-$settings->_Path ist der Pfad zu dem Verzeichnis mit den Dateien:

_____________________________

header("Content-Type: $individuelMimeType");
header("Content-Disposition: attachment; filename="$name"");
readfile($settings->_Path  . "/". $physicalName);
_____________________________

Wie gesagt, das funktioniert bei 95% der Dateien; warum es bei einigen nicht geht, weiß ich nicht. Es wird ja das gleiche Skript aufgerufen, nur eben versch. Werte mitgegeben.
Ich dachte erst, das Problem läge bei dem Download-Skript, aber nimmt man die drei Zeilen raus und gibt zB. nur die mitgegebenen Werte aus, funktioniert es. Nach der Fehlermeldung im Netscape dachte ich, die Dateien wären schrott ode so, aber das ist es auch nicht. Auch, dass sie als .dat gespeichert werden ist nicht das Problem. Ich habe sie testweise mit der richtigen Endung benannt und auch dann ging es nicht.

Hatte jemand mal ein ähnliches Problem oder einfach nur einen Vorschlag für mich?

Grüße, basi

  1. Hi,

    Fehlermeldung im IE 5:

    die Fehlermeldungen des IE sind leider potentiell aussagefrei.

    Fehlermeldung im Netscape 7: "Das Dokument enthält keine Daten." (als alert-message, Fenster bleibt leer)

    Genau das ist passiert: Die Rückgabe enthielt keine Daten, obwohl sie welche hätte haben müssen. Dein Script ist offenbar entweder vor seinem Ende abgebrochen, oder es hat zwar alles getan, was ihm gesagt wurde, aber mit fehlenden Daten; beispielsweise weil eine Datei nicht geöffnet werden konnte, leer war o.ä. Ein DNS-Problem liegt nicht vor; möglicherweise hat der Server (oder eine Firewall, Proxy o.ä.) die Verbindung ob irgendeinen Grundes gekappt.

    Ich habe alle Variablen überprüft, mit denen der Pfad zur Datei generiert wird -> alles korrekt.

    Schreibe Logfiles mit relevanten Daten raus (gesetzte Header, Anzahl der _wirklich_ gesendeten Bytes, "Stelle x im Code erreicht", "Datei x hat folgende Eigenschaften" etc.).

    Cheatah

    --
    X-Will-Answer-Email: No
    X-Please-Search-Archive-First: Absolutely Yes
    1. Genau das ist passiert: Die Rückgabe enthielt keine Daten, obwohl sie welche hätte haben müssen. Dein Script ist offenbar entweder vor seinem Ende abgebrochen, oder es hat zwar alles getan, was ihm gesagt wurde, aber mit fehlenden Daten; beispielsweise weil eine Datei nicht geöffnet werden konnte, leer war o.ä. Ein DNS-Problem liegt nicht vor; möglicherweise hat der Server (oder eine Firewall, Proxy o.ä.) die Verbindung ob irgendeinen Grundes gekappt.

      Schreibe Logfiles mit relevanten Daten raus (gesetzte Header, Anzahl der _wirklich_ gesendeten Bytes, "Stelle x im Code erreicht", "Datei x hat folgende Eigenschaften" etc.).

      Hi, erstmal danke für Info.

      Nach Logfileschreiben habe ich festgestellt, dass bei den nicht funktionierenden Downloads das Skript nach dem Festlegen der Header abbricht (sprich: Kein Logfileeintrag nach readfile() mehr).
      Die Eigenschaften der Datei werden korrekt ausgelesen, an ihr liegt es also nicht.
      Die Header habe ich über apache_request_headers() im downloadskript geholt: sie sind identisch, egal ob der download geklappt hat oder nicht. Daraus schließe ich jetzt, dass das Abbrechen des Skriptes nichts mit den Headern zu tun hat, da diese beim funktionierendem Download gleich sind.

      Weißt Du noch eine weitere Möglichkeit?

      1. Hi,

        Nach Logfileschreiben habe ich festgestellt, dass bei den nicht funktionierenden Downloads das Skript nach dem Festlegen der Header abbricht (sprich: Kein Logfileeintrag nach readfile() mehr).

        [...]

        Weißt Du noch eine weitere Möglichkeit?

        jetzt musst Du herausfinden, _warum_ das Script abbricht. Fokussiere Deine Logfile-Einträge entsprechend, sorge zudem für eine lückenlose Fehlerbehandlung ("or die" etc.).

        Cheatah

        --
        X-Will-Answer-Email: No
        X-Please-Search-Archive-First: Absolutely Yes
        1. jetzt musst Du herausfinden, _warum_ das Script abbricht. Fokussiere Deine Logfile-Einträge entsprechend, sorge zudem für eine lückenlose Fehlerbehandlung ("or die" etc.).

          Okay, Zwischenmeldung:

          1. Wenn ich anstatt readfile() file() benutze (und die Header auskommentiere) und das Array dann ausgebe, ist es korrekt gefüllt, sprich, die Datei wird korrekt ausgelesen.
          Wenn ich nur die Header auskommentiere, zeigt readfile() den Inhalt der Dateien, bei denen der Download funzt an, bei denen der Download nicht geht, kommt die am Anfang genannte Fehlermeldung.

          2. Wenn ich an das readfile() ein 'or die()' anfüge, wird dieses nicht ausgeführt:
          $test = readfile($settings->_Path  . "/". $physicalName) or die("Fehler: Skript stirbt.");
          die() würde ausgeführt werden, wenn der Ausdruck links false ist. Da readfile() int zurückgibt, habe ich auch getestet, ob $test == 0 ist und in dem Fall ein die() abgesetzt. Das kam aber auch nicht.

          Daraus schließe ich nun, das irgend etwas mit readfile so falsch läuft, dass nicht einmal die or-Bedingung durchlaufen wird oder $test nicht null ist, was aber bedeuten müsste, dass zumindest irgend etwas im Browser angezeigt werden müsste.

          Die Zwischenmeldung gebe ich, weil Du ev. nen weiteren Hint hast, der mir bei der Suche weiterhilft. Ich denke und probiere, aber ein Schubs in die richtige Richtung hilft sicher.

          1. Hi,

            1. Wenn ich anstatt readfile() file() benutze (und die Header auskommentiere) und das Array dann ausgebe, ist es korrekt gefüllt, sprich, die Datei wird korrekt ausgelesen.

            die beiden Funktionen lassen sich nicht einfach so austauschen. Hast Du die Unterschiede beachtet?

            bei denen der Download nicht geht, kommt die am Anfang genannte Fehlermeldung.

            Also weiterhin "Document contains no data", keine textuelle Ausgabe im Response-Body?

            1. Wenn ich an das readfile() ein 'or die()' anfüge, wird dieses nicht ausgeführt:

            Das lässt darauf schließen, dass im Fehlerfall readfile() nicht ausgeführt wird, also nicht mal die Chance eines Fehlers hat - wobei ich noch mal auf die Möglichkeit der Verbindungsunterbrechung durch z.B. einen Proxy hinweisen möchte.

            die() würde ausgeführt werden, wenn der Ausdruck links false ist. Da readfile() int zurückgibt,

            Da ist entweder die Doku oder PHP ungenau:

            """
            int readfile ( string filename [, int use_include_path])
            [...] Wenn ein Fehler auftritt wird FALSE zurückgegeben [...]
            """

            Die Zwischenmeldung gebe ich, weil Du ev. nen weiteren Hint hast, der mir bei der Suche weiterhilft.

            Es macht Spaß, Dir zu helfen, weil man sieht, dass die Tipps fruchten. Leider kenne ich aber die Lösung nicht und kann daher auch nicht wirklich die richtige Richtung anzeigen. Ich denke aber, Du solltest untersuchen, ob die Verbindung zwischen Client und Server verantwortlich sein kann.

            Cheatah

            --
            X-Will-Answer-Email: No
            X-Please-Search-Archive-First: Absolutely Yes
            1. die beiden Funktionen lassen sich nicht einfach so austauschen. Hast Du die Unterschiede beachtet?

              Es macht Spaß, Dir zu helfen, weil man sieht, dass die Tipps fruchten. Leider kenne ich aber die Lösung nicht und kann daher auch nicht wirklich die richtige Richtung anzeigen. Ich denke aber, Du solltest untersuchen, ob die Verbindung zwischen Client und Server verantwortlich sein kann.

              Nach Deiner Frage, ob ich die Unterschiede der Funktionen beachtet habe, habe ich mit die nochmal durchgelesen und unter readfile() gelesen:

              "Folgende Verbindungsmöglichkeiten können Sie im Parameter filename angeben:
              "http://" - Öffnen per http
              "ftp://" - Öffnen per ftp - wird fehlschlagen, wenn der Server keinen passiven
              Modus unterstützt
              Alles andere - Öffnen vom lokalen Dateisystem"

              Ausserdem hast Du Verbindung zw. Client und Server angesprochen. Also habe ich die Pfadvariable $settings->_Path geändert, die in readfile() benutzt wird. Ursprünglich ging die einfach vom root: "/data/htdocs/intranet/.../.../dateien/"
              Jetzt sieht sie so aus: "http://192.168.0.1/intranet/.../.../dateien/"

              Damit geht's.
              Also geht es über http. Was mir fehlt, ist die Erklärung. Eigentlich müssten dann doch alle Dateien gehen oder eben nicht. Und wieso muss ich einem Skript, welches ja auf dem Server liegt, die IP geben, das root langt doch eigentlich?

              Es geht, ich bin froh, aber hast Du dafür eine Erklärung?
              Auf jeden Fall: danke.

              Gruß, basi

              1. Hi,

                Nach Deiner Frage, ob ich die Unterschiede der Funktionen beachtet habe, habe ich mit die nochmal durchgelesen und unter readfile() gelesen:

                ich meinte eher, dass readfile() im Gegensatz zu file() die gelesenen Daten direkt nach STDOUT schreibt.

                Ausserdem hast Du Verbindung zw. Client und Server angesprochen. Also habe ich die Pfadvariable $settings->_Path geändert,

                Das ist bereits die Serverseite - die Du nun zwar zu einem eigenen Client gemacht hast, aber die Strecke zwischen dem "ursprünglichen" Client und Server bleibt unverändert.

                Ursprünglich ging die einfach vom root: "/data/htdocs/intranet/.../.../dateien/"
                Jetzt sieht sie so aus: "http://192.168.0.1/intranet/.../.../dateien/"

                Das ist ein weiterer HTTP-Roundtrip, und somit liest Du keine Datei mehr aus, sondern eine Ressource.

                Damit geht's.

                Krass.

                Also geht es über http. Was mir fehlt, ist die Erklärung.

                Das kann ich verstehen ... Ich kann nur auf ein Problem mit dem Filesystem schließen, welches aus irgendwelchen Gründen im Zusammenhang mit Deinem PHP-Script auftritt. Laufen die PHP-Forks der Apache-Worker eventuell nicht immer unter dem selben User?

                Es geht, ich bin froh, aber hast Du dafür eine Erklärung?

                Nicht wirklich, wie Du merkst. Hält das Error-Log des Servers vielleicht Informationen bereit, z.B. segmentation faults?

                Cheatah

                --
                X-Will-Answer-Email: No
                X-Please-Search-Archive-First: Absolutely Yes