Downloads to users not passing file size

I’m using the following code to allow users to download files from my hosted website. It works, but it’s not passing the filesize to a browser. I’ve tried both:

header('Content-Length: ’ . filesize($filename));
and:
$size=filesize($filename)
header('Content-Length: ’ . $size);

Here’s the full code:

<?php
error_reporting(E_ALL);
ini_set('display_errors', '1');

function usdloader($filenumber=NULL){
    require '../../php/PDO_Connection_Select.php';

    if (!$pdo = PDOConnect("foxclone_data")) {
        exit("unable to connect to database"); }

   $test = $pdo->query("SELECT `filename` FROM `files` WHERE `id` = $filenumber");
   $filename = $test->fetchColumn();

  if (!file_exists($filename)) {
        exit("Requested file ($file) does not exist");
      }
  else {
    $file_path  = './' . $filename;
    $size = filesize($filename);
        header('Content-Description: File Transfer');
        header('Content-Type: ' . mime_content_type($filename));
        header('Content-Disposition: attachment; filename='.$filename);
        header('Expires: 0');
        header("Cache-Control: public, must-revalidate, post-check=0, pre-check=0");
        header('Pragma: public');
        header('Content-Length: ' . filesize($filename));
        readfile($filename); // Download the file
        flush();
    }
}
usdloader($_GET["f"]);

What am I doing wrong?

Thanks in advance

What you are getting back from filesize function? Output it, maybe the file path is not correct, filesize function expects a file path, so maybe you could try using filesize($file_path); instead of filesize($filename);. I can’t be sure but try and see if your file really exists and what filesize function returns.

The file exists and downloads correctly. It’s just not passing the filesize to the browser. I’ll try your suggestion and let you know the outcome.

The script is in the same folder as the files to be downloaded. I tried setting $file_path = ‘./’. $filename and changed the header to header('Content-Length: ’ . filesize($filepath));
It’s still not passing the filesize.

Does filesize function return file size in number?

I think I have experienced this problem long time ago. What else you could try is try deleting flush(); function call. And try to insert Content-Length header code before Content-Disposition header, and let me know how that works out.

Also this code for me worked correctly at least: https://gist.githubusercontent.com/MasterEx/1135904/raw/30f2111a8c395c86c7c8f4496ac2dfd7daefae27/file.php

If anything else fails, try this, could be that some headers in your script are not accepted:

header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($filename));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
ob_clean();
flush();
readfile($filename);
exit;

Putting the content-length header before the content-disposition header didnt work. My file types are .tar.gz, .deb, and .iso. That’s why I’m using the header:

header('Content-Type: ' . mime_content_type($filename));

I don’t think that:

header('Content-Type: application/octet-stream');

will work. As I said, the files download correctly. It’s just not sending the file size. I’ll give your code a try.

Still no luck. The only thing left is to add case statement for each file type instead of using mime_content_type in the Content-Type header.

This is from the php documentation for filesize() -

Note: Because PHP’s integer type is signed and many platforms use 32bit integers, some filesystem functions may return unexpected results for files which are larger than 2GB.

What is the actual filesize of the file you are trying to download and did you ever display/log what value the filesize() function returns?

Have you also checked on more than one browser, what browser were you using at the time?
It’s strange because for me it works the way it should.

The files are all under 900Mb. I’ve tried using Chromium, Opera, and Firefox. Filesize(filename) returns correct values for each file.

Just found this - Apache doesn't show filesize/duration during downloading .dmg in browser? - Stack Overflow

One of the files is a tar.gz, I don’t think I can set it to SetEnv no-gzip dont-vary

That’s not what the setting has anything to do with.

The setting causes the content you output to be zipped, which the browser then un-zips, back to the original. So, for an already compressed file, it gets compressed again, before it is sent.

Okay, I’ll give it a try in the morning. I have to go shopping before I go to bed. I’ve been at this all day.

Have a good evening and thanks to both of you.

I decided to give that a try before going shopping. It works! The file size and time left now show. :smiley:

@phdr - Thanks for finding that. I never came across that in my searches.
@Erasus - I appreciate your assistance and the time you spent trying to help.

Glad you have sorted that out with @phdr help. :slight_smile:

Sponsor our Newsletter | Privacy Policy | Terms of Service