Why does readfile($filename) corrupt downloads?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • deko

    Why does readfile($filename) corrupt downloads?

    I need to allow users to download files from a directory that is not
    publicly accessible. To do this, I use a download script:

    header("Content-Type: application/octet-stream");
    header("Content-Disposition: attachment; filename=".$fil ename);
    readfile($fullp ath);

    I've also tried using header("Content-Type: application/force-download")
    instead of header("Content-Type: application/octet-stream"), but get the
    same results - the downloaded file gets corrupted and cannot be read.

    If I move the same file to /public_html and point a link to
    http://www.mysite.com/filename.zip, it downloads fine and does not get
    corrupted.

    Am I using readfile correctly? Is there a more reliable way to download
    files from directories that are not publicly accessible?

    Thanks in advance.


  • deko

    #2
    Re: Why does readfile($filen ame) corrupt downloads?

    > publicly accessible. To do this, I use a download script:[color=blue]
    >
    > header("Content-Type: application/octet-stream");
    > header("Content-Disposition: attachment; filename=".$fil ename);
    > readfile($fullp ath);
    >
    > I've also tried using header("Content-Type: application/force-download")
    > instead of header("Content-Type: application/octet-stream"), but get the
    > same results - the downloaded file gets corrupted and cannot be read.
    >
    > If I move the same file to /public_html and point a link to
    > http://www.mysite.com/filename.zip, it downloads fine and does not get
    > corrupted.
    >
    > Am I using readfile correctly? Is there a more reliable way to download
    > files from directories that are not publicly accessible?[/color]

    I may have discovered the problem. The page in which the link to the
    download script resides is SSL-encrypted. So perhaps the download is going
    over an encrypted connection or something. I discovered this by putting the
    link to the download script in page that is not SSL-encrypted. The download
    works fine from regular page. But this raises another question - how to
    download over an SSL connection?


    Comment

    • deko

      #3
      Re: Why does readfile($filen ame) corrupt downloads?

      > I may have discovered the problem. The page in which the link to the[color=blue]
      > download script resides is SSL-encrypted. So perhaps the download is[/color]
      going[color=blue]
      > over an encrypted connection or something. I discovered this by putting[/color]
      the[color=blue]
      > link to the download script in page that is not SSL-encrypted. The[/color]
      download[color=blue]
      > works fine from regular page. But this raises another question - how to
      > download over an SSL connection?[/color]

      Correction... with further testing, the issue clearly has something to do
      with the download script.

      Here is a non-SSL-encrypted page from which the download is initiated:

      <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01
      Transitional//EN"http://www.w3.org/TR/html4/loose.dtd">
      <html>
      <head>
      <meta http-equiv='Content-Type' content='text/html; charset=iso-8859-1'>
      <link href='../../style.css' rel='stylesheet ' type='text/css'>
      <title>test</title>
      </head>
      <?php
      echo "
      <body>
      <div id='bodyContent ' style='height:8 00px'>
      <table border='0' cellpadding='0' cellspacing='0' width='760'>
      <tr>
      <td><img src='../../images/headerbar/headerbar1.jpg</td>
      <td><img src='../../images/headerbar/headerbar2.jpg' </td>
      </tr>
      </table>
      <!-- <a href='mydirecto ry/myfile.zip'>myf ile.zip</a> -->
      <a href='dlcounter .php?file=myfil e.zip'>myfile.z ip</a>
      </div>
      </body>
      </html>
      ";
      ?>

      If I swap the commented line with the uncommented line, it works fine. The
      way it is now, I get a corrupted download.

      The three operative lines in the download script are:

      header("Content-Type: application/octet-stream")
      header("Content-Disposition: attachment; filename=".$fil ename);
      readfile($fullp ath);

      Could the issue be the HTTP variable ?file=myfile.zi p?
      Perhaps the variables I'm using in the download script?
      Some aberrant headers somewhere?


      Comment

      • Alvaro G Vicario

        #4
        Re: Why does readfile($filen ame) corrupt downloads?

        *** deko wrote/escribió (Mon, 14 Mar 2005 04:32:27 GMT):[color=blue]
        > I need to allow users to download files from a directory that is not
        > publicly accessible. To do this, I use a download script:
        >
        > header("Content-Type: application/octet-stream");
        > header("Content-Disposition: attachment; filename=".$fil ename);
        > readfile($fullp ath);
        >
        > I've also tried using header("Content-Type: application/force-download")
        > instead of header("Content-Type: application/octet-stream"), but get the
        > same results - the downloaded file gets corrupted and cannot be read.[/color]

        Make you sure aren't adding any extra blanks. The <? and ?> tags should be
        the first and last chars in the script file respectively.

        Comment

        • Hans van Kranenburg

          #5
          Re: Why does readfile($filen ame) corrupt downloads?

          deko wrote:[color=blue]
          > I need to allow users to download files from a directory that is not
          > publicly accessible. To do this, I use a download script:
          >
          > header("Content-Type: application/octet-stream");
          > header("Content-Disposition: attachment; filename=".$fil ename);
          > readfile($fullp ath);[/color]



          I used this yesterday for downloading a 100MB protected file (binary is
          no problem) over https:

          <?php

          $file = '100mb.bin';
          $fp = fopen($file, 'rb');

          header("Content-Type: application/octet-stream");
          header("Content-Length: " . filesize($file) );

          fpassthru($fp);
          exit;

          ?>



          --
          "He who asks a question is a fool for five minutes;
          he who does not ask a question remains a fool forever"

          Comment

          • deko

            #6
            Re: Why does readfile($filen ame) corrupt downloads?

            > Make you sure aren't adding any extra blanks. The <? and ?> tags should be[color=blue]
            > the first and last chars in the script file respectively.[/color]

            I may discovered the problem. I was trying to use the same download script
            for "secure" and "public" downloads, like this:

            <?php
            session_start() ;
            $filename = trim($_GET[file]);
            if ($_SESSION['uid'])
            {
            $file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
            }
            else
            {
            $file = 'http://www.clearpoints ystems.com/publicdownload/'.$filename;
            }
            header("Content-Disposition: attachment; filename=".$fil ename);
            header("Content-Length: ".filesize($fil ename));
            readfile($filen ame);
            exit;

            I just tried this, and it appeared to work:

            <?php
            header("Content-Disposition: attachment;
            filename=/home/myacct/secure/test.zip");
            header("Content-Length: ".filesize('hom e/myacct/secure/test.zip'));
            readfile("home/myacct/secure/test.zip");
            ?>

            Perhaps the problem was the headers getting screwed up with session_start.
            Nevertheless, I'm wondering if readfile() will work the same with binary and
            text files. Do I need to do anything differently for binary files?


            Comment

            • Alvaro G Vicario

              #7
              Re: Why does readfile($filen ame) corrupt downloads?

              *** deko wrote/escribió (Thu, 17 Mar 2005 05:13:26 GMT):[color=blue]
              > <?php
              > session_start() ;
              > $filename = trim($_GET[file]);
              > if ($_SESSION['uid'])
              > {
              > $file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
              > }
              > else
              > {
              > $file = 'http://www.clearpoints ystems.com/publicdownload/'.$filename;
              > }
              > header("Content-Disposition: attachment; filename=".$fil ename);
              > header("Content-Length: ".filesize($fil ename));
              > readfile($filen ame);
              > exit;[/color]

              You don't use variable $file, do you?


              --
              -- Álvaro G. Vicario - Burgos, Spain
              -- Don't e-mail me your questions, post them to the group
              --

              Comment

              • deko

                #8
                Re: Why does readfile($filen ame) corrupt downloads?

                > > <?php[color=blue][color=green]
                > > session_start() ;
                > > $filename = trim($_GET[file]);
                > > if ($_SESSION['uid'])
                > > {
                > > $file = '/home/myacct/secure/'.$_SESSION['uid'].'/'.$filename;
                > > }
                > > else
                > > {
                > > $file = 'http://www.clearpoints ystems.com/publicdownload/'.$filename;
                > > }
                > > header("Content-Disposition: attachment; filename=".$fil ename);
                > > header("Content-Length: ".filesize($fil ename));
                > > readfile($filen ame);
                > > exit;[/color]
                >
                > You don't use variable $file, do you?[/color]

                air code error...

                $filename should be $file in the last few lines.

                In any case, I got it working. I wrote a download script just for secure
                downloads and put the download script in cgi-bin and call it from the
                SSL-encrypted private page. The private files are located outside of
                document root, so I guess it's about as secure as it can get, or at least as
                secure as it needs to be. Raj Shekhar sent me something about Pear - I
                looked at the web page and tried to read the manual but I still have no idea
                what Pear is or why I should use it.


                Comment

                Working...