Why does download script never save the last chunk?

Collapse
X
 
  • Time
  • Show
Clear All
new posts
  • empiresolutions
    New Member
    • Apr 2006
    • 162

    Why does download script never save the last chunk?

    I'm using the following script to download large file (>100Mb). It works well except that it seems to not ever save the final chunk. If the file is 149,499 on the server, it finishes its download at 145,996. Why? How do I get the last 2% or so to flush and complete the download? Thank much for your help.

    FYI, this also happens the same on smaller files so its not stopping for time or file size issues.

    Code:
     
    $path = "the/file/path.mp4";
    
    $headsize = get_headers($path,1);
    
    $ext = str_from_last_occurrence($_vars['filepath'],".");
    
    if ($ext=="mp3") { $type = "audio"; }
    elseif ($ext=="mp4") { $type = "video"; }
    
    function readfile_chunked($filename,$retbytes=true) {
    
    	// Stream file
    	$handle = fopen($filename, 'rb');
    	$chunksize = 1*(1024*1024); // how many bytes per chunk
    	$buffer = '';
    	$cnt =0;
    
       if ($handle === false) {
           return false;
       }
    
       while (!feof($handle)) {
           $buffer = fread($handle, $chunksize);
           echo $buffer;
           ob_flush();
           flush();
           if ($retbytes) {
               $cnt += strlen($buffer);
           }
       }
    
       $status = fclose($handle);
    
       if ($retbytes && $status) {
           return $cnt; // return num. bytes delivered like readfile() does.
       }
    
       return $status;
    
    }
    
    header('Cache-Control: no-cache, no-store, max-age=0, must-revalidate');
    header("Content-type: ".$type."/".$ext);
    header('Content-Length: ' . (string)($headsize['Content-Length']));
    header('Content-Disposition: attachment; filename="'.str_from_last_occurrence($_vars['filepath'],"/").'"');
    header("Content-Transfer-Encoding: binary");
    
    readfile_chunked($path);
    
    exit;
  • HaLo2FrEeEk
    Contributor
    • Feb 2007
    • 404

    #2
    I'm using this exact same function and it works fine for me. I can download huge files just fine. Are the file you're downloading located on your own server? If so then don't bother getting the headers, that's just wasteful, use filesize() instead. Here's the download headers I'm setting, unmodified from my site's code, so they won't be plug n' play for you:

    Code:
    header("Cache-Control: ");
    header("Pragma: ");
    header("Content-type: application/octet-stream");
    header("Content-Disposition: attachment; filename=\"".$download."\"");
    header("Content-length:".(string)(filesize($path.$download)));
    readfile_chunked($path.$download);

    Comment

    • empiresolutions
      New Member
      • Apr 2006
      • 162

      #3
      the files are hosted on a CDN.

      Comment

      • code green
        Recognized Expert Top Contributor
        • Mar 2007
        • 1726

        #4
        You are not checking fread for error, so if the last chunk fails,
        you will not see it.

        Comment

        • empiresolutions
          New Member
          • Apr 2006
          • 162

          #5
          can you give me an example of how to read the error?

          Comment

          • code green
            Recognized Expert Top Contributor
            • Mar 2007
            • 1726

            #6
            fread returns a string or FALSE on error.
            This doesn't tell you the problem of course.
            But with error_reporting enabled you may be given a clue
            Last edited by code green; Feb 10 '11, 12:15 PM. Reason: Additional Info

            Comment

            • empiresolutions
              New Member
              • Apr 2006
              • 162

              #7
              $buffer = fread($handle, $chunksize);
              echo $buffer;
              Does this not count as checking for an error? It returns nothing important that I see.

              Comment

              • code green
                Recognized Expert Top Contributor
                • Mar 2007
                • 1726

                #8
                This does not handle anything when FALSE is returned.
                Is error_reporting enabled in php.ini?

                Comment

                • empiresolutions
                  New Member
                  • Apr 2006
                  • 162

                  #9
                  error_reporting = E_ERROR;

                  Comment

                  • code green
                    Recognized Expert Top Contributor
                    • Mar 2007
                    • 1726

                    #10
                    This settings shows only the basic errors.
                    When debugging use
                    Code:
                    error_reporting(E_ALL | E_STRICT);
                    At the beginning of scripts.
                    File errors will then be output

                    Comment

                    Working...