Jan L.: PDF -> fpassthru

Hallo allerseits,

Ich möchte gerne pdf-Dateien, die in einem Verzeichnis 'unterhalb' des 'document_root' liegen, zum Runterladen anbieten.
Das habe ich mit einem Beispiel, das ich der PHP-Doku gefunden habe, versucht.

...
$fp = fopen($file, "r");
header("Content-type: application/pdf");
fpassthru($fp);
fclose($fp);

Allerdings erhalte ich mit dieser Methode immer nur die Fehlermeldung 'Diese Datei ist beschädigt und kann nicht repariert werden'. Wenn ich diese Datei alledings in ein Verzeichnis lege, auf das Apache Zugriff hat, und sie direkt verlinke, funktioniert alles wunderbar.

Kann mir jemand sagen, was ich falsch mache und wie sich das lösen läßt?

Danke und Gruß, Jan

  1. Hi

    Ich möchte gerne pdf-Dateien, die in einem Verzeichnis 'unterhalb' des 'document_root' liegen, zum Runterladen anbieten.
    Das habe ich mit einem Beispiel, das ich der PHP-Doku gefunden habe, versucht.

    ...
    $fp = fopen($file, "r");
    header("Content-type: application/pdf");
    fpassthru($fp);
    fclose($fp);

    Allerdings erhalte ich mit dieser Methode immer nur die Fehlermeldung 'Diese Datei ist beschädigt und kann nicht repariert werden'. Wenn ich diese Datei alledings in ein Verzeichnis lege, auf das Apache Zugriff hat, und sie direkt verlinke, funktioniert alles wunderbar.

    Ja sicher ist das so, denn Dateien, auf die der wwwrun keinen Zugriff hat, kann er auch nicht ausliefern, ergo: Datei in ein Verzeichnis, auf das der Apache _Leserechte_ hat, und gut 'is =)

    Fabian

    1. Hallo Fabian,

      Ja sicher ist das so, denn Dateien, auf die der wwwrun keinen Zugriff hat, kann er auch nicht ausliefern, ergo: Datei in ein Verzeichnis, auf das der Apache _Leserechte_ hat, und gut 'is =)

      Das hab ich jetzt mal getestet. Der Fehler bleibt allerdings weiterhin bestehen.

      Gruß, Jan

      1. Hallo Jan,

        die pdf-Datei kann natürlich im lokalen Dateisystems des Host liegen, wo sie will, Hauptsache der wwwrun hat Zugriff darauf. Fabina  meinte das bestimmt auch, hat sich nur missverständlich ausgedrückt. Unter "Apache" versteht man allzuschnell den HTTP-Dienst des Apache, und _der_ soll ja gerade keinen Zugriff haben.

        <?php
         if ($HTTP_POST_VARS["filename"]=="dokument.pdf")
          {
            $filename=$HTTP_POST_VARS['filename'];
            header("Content-type: application/x-msdownload");
            header("Content-Disposition: attachment; filename=$filename");
            readfile($HTTP_POST_VARS["filename"]);
          }
          else
          {
            die("Datei konnte nicht gefunden werden<br /> ");
          }
        ?>

        So funktioniert es, ist aber auch nicht richtig, da hezt keine Applikationsempfehlung mehr gegeben wird. Die Datei wird also nur noch zum Download angeboten. Außerdem stört mich, dass im Downloadfenster so steht:

        Downloaden einer Datei vin diesem Ort:
         getfile.php von testserver

        getfile.php ist das obige Skript.

        Da hätte ich doch ganz gerne den Dateinamen der zu downloadenden <blödes Wort> Datei stehen.

        Grüße

        Tom

        1. Hallo Tom,

          die pdf-Datei kann natürlich im lokalen Dateisystems des Host liegen, wo sie will, Hauptsache der wwwrun hat Zugriff darauf. Fabina  meinte das bestimmt auch, hat sich nur missverständlich ausgedrückt. Unter "Apache" versteht man allzuschnell den HTTP-Dienst des Apache, und _der_ soll ja gerade keinen Zugriff haben.

          Danke für die Erklärung. Ob Fabian das freut, daß du ihn in 'Fabina' umgetauft hast? ;-)

          <?php
          if ($HTTP_POST_VARS["filename"]=="dokument.pdf")
            {
              $filename=$HTTP_POST_VARS['filename'];
              header("Content-type: application/x-msdownload");
              header("Content-Disposition: attachment; filename=$filename");
              readfile($HTTP_POST_VARS["filename"]);
            }
            else
            {
              die("Datei konnte nicht gefunden werden<br /> ");
            }
          ?>

          Vielen Dank auch dafür. Das funktioniert zumindest.

          So funktioniert es, ist aber auch nicht richtig, da hezt keine Applikationsempfehlung mehr gegeben wird. Die Datei wird also nur noch zum Download angeboten. Außerdem stört mich, dass im Downloadfenster so steht:

          Downloaden einer Datei vin diesem Ort:
          getfile.php von testserver

          getfile.php ist das obige Skript.

          Da hätte ich doch ganz gerne den Dateinamen der zu downloadenden <blödes Wort> Datei stehen.

          Mozilla 1.1 gibt der Datei bei mir den richtigen Namen, hängt aber noch ein .php an den Dateinamen an. Der IE macht es so, wie du gesagt hast.

          Übrigens: Was ist an dem Beispiel aus meinem ersten Posting, das ich aus der PHP-Doku entnommen habe, denn falsch? Wenn ich das dort richtig verstanden habe, ist es doch genau dafür da.

          Gruß, Jan

          1. Hallo Jan.

            Danke für die Erklärung. Ob Fabian das freut, daß du ihn in 'Fabina' umgetauft hast? ;-)

            Ich hoffe, er verzeiht es mir. Hat er eben einen gut.

            So funktioniert es, ist aber auch nicht richtig, da hezt keine Applikationsempfehlung mehr gegeben wird. Die Datei wird also nur noch zum Download angeboten. Außerdem stört mich, dass im Downloadfenster so steht:

            Downloaden einer Datei vin diesem Ort:
            getfile.php von testserver

            getfile.php ist das obige Skript.

            filesize wird mir im MSIE auch nicht angezeigt, obwohl ich den Size-Header noch hinzugefügt hatte.

            außerdem soll man da angeblich noch den Server informieren in der httpd.conf, dass er nun auch pdf-files handlen kann. Beispiel hier für Flashfiles. Für pdf kenne ich die Angabe nicht

            AddType application/x-shockwave-flash swf

            Da hätte ich doch ganz gerne den Dateinamen der zu downloadenden <blödes Wort> Datei stehen.

            Mozilla 1.1 gibt der Datei bei mir den richtigen Namen, hängt aber noch ein .php an den Dateinamen an. Der IE macht es so, wie du gesagt hast.

            Übrigens: Was ist an dem Beispiel aus meinem ersten Posting, das ich aus der PHP-Doku entnommen habe, denn falsch? Wenn ich das dort richtig verstanden habe, ist es doch genau dafür da.

            Das ist ja mein reden, dass die ganzen Beispiele immer unvollständig sind. Kann man aber wohl uch nichts machen bei den häufigen Versionswechseln.

            Liebe Grüße aus http://www.braunschweig.de

            Tom

            1. Hi

              Danke für die Erklärung. Ob Fabian das freut, daß du ihn in 'Fabina' umgetauft hast? ;-)

              Ich hoffe, er verzeiht es mir. Hat er eben einen gut.

              *nachdenkwieertomeinenauswischenkann*...

              Okay, ich verzeih' dir. =)

              Fabian
              [scnr]

          2. Hallo Jan,

            fpassthru() kann man prinzipiell auch so verwenden, aber man hat den Nachteil, daß man die Datei - im Gegensatz zu readfile() - extra öffnen und schließen muß. Unter Windows muß man beim fopen() darauf achten, die Datei auch im Binärmodus geöffnet wird:
            $fp = fopen($file, "rb");
            Ich vermute, da lag der Haken.

            Schönen Gruß

            Rainer

        2. Hallo Tom nochmal,

          Hab jetzt noch ein wenig herumprobiert und folgendes ist dabei rausgekommen:

          <?php
           if ($_GET["filename"]=="dokument.pdf")
            {
              $filename=$_GET['filename'];
              header("Content-Length: ".filesize($filename));
              header("Content-type: application/pdf");
              readfile($filename);
            }
            else
            {
              die("Datei konnte nicht gefunden werden<br /> ");
            }
          ?>

          So scheint es tadellos zu funktionieren. Und das PDF wird auch, falls im Browser so eingestellt, direkt angezeigt.

          Gruß, Jan