PHP Content-Length header not working
Asked Answered
B

7

10

I am trying to use this code to download a .zip file

<?php
    $file = "something.zip";
    $size = filesize($file);
    header('Content-type: application/octet-stream');
    header("Content-length: $size");
    header('Content-Disposition: attachment; filename="downloaded.zip"');
    readfile($file);
?>

but it does not seem to work, even when I try to set the filesize to a number like header("Content-length: 567247784");. I only get a file that either has no size declared, or a small file size like 28 bytes.

I looked at this question, and I think I have the same problem as the poster, but his solution is "there was a server problem". I think I also have a server configuration issue, but his answer does not help me at all.

Benefit answered 11/1, 2014 at 16:48 Comment(2)
Do not output anything before you set your headers.Shamanism
Whoops, I forgot to remove that after trying to see if the filesize was found. It still does not work without that, though.Benefit
W
28

it has to do with mod_deflate getting in the way. I spent a day messing with .htaccess and trying a million different things, in the end this fixed it but I can't really explain why:

    header('Content-Length: '.$filesize);
    header("Content-Range: 0-".($filesize-1)."/".$filesize);

I want to add that my PHP was configured with less than 256MB of memory.

With answered 1/6, 2015 at 9:25 Comment(3)
apparently you can even simply set Content-Range: 0. I have observed no difference. This is really weird.Bukhara
doesn't worked for me. I had to remove the header "Content-length".Sarracenia
I might imagine, that the server (which is in the end the one who sends the data to the client and not PHP itself) compresses the data and might remove that header line because of that (it would have to change it anyway, since the compressed amount of data is different than whatever you tell PHP and you can't know that number). I just don't understand why mod_deflate doesn't set or update that header line by itself. I assume that it must be either a bug in mod_deflate or the design of server mods simply doesn't offer this functionality for some reason.Aristocrat
K
3

Sometimes mod_deflate isn't the culprit. There's an Apache env variable that governs trusting CGI-like scripts with Content-Length setting.

SetEnv ap_trust_cgilike_cl 1

Without it, Apache will ignore Content-Length set by PHP scripts.

Kipper answered 8/5 at 20:19 Comment(1)
In my experience, enabling this configuration is necessary also when using php-fpm. The issue appears to be related to a security fix introduced in Apache 2.4.59 (as documented here: link). Consider using SetEnvIf instead of SetEnv for improved security and address specific URLs.Preclinical
S
1

I think the easiest and the best way is:

$head = array_change_key_case(get_headers($file, TRUE));
                    $filesize = $head['content-length'];
Shelby answered 17/3, 2014 at 12:21 Comment(0)
M
0

Try to remove the trailing ?> in cases like this. The newlines or whitespace after the ?> can alter the result.

Usually, the webserver will set the Content-Length header automatically.

For debugging, you can use the very awesome http://fiddler2.com/ to inspect the headers or even compose an arbitrary request to test your assumptions. Fiddler will warn if the content body is different from the Content-Length header.

Mahratta answered 11/1, 2014 at 17:27 Comment(1)
This only seems to give me higher numbers (~260 bytes instead of ~20). I'll try using Fiddler2.Benefit
K
0

Following on from TeeraMusic great analysis https://mcmap.net/q/1042354/-php-content-length-header-not-working which identified mod_deflate as the culprit 👍


Option 1: (Disable DEFLATE for this request)

apache_setenv('no-gzip', '1');

Proper way to stop mod_deflate for this request.


Option 2: (Disable DEFLATE for all requests of this Content-Type)

The option which controls which files are DEFLATE will most likely be in your .htaccess or httpd.conf:

AddOutputFilterByType DEFLATE "application/atom+xml" \
                              "application/javascript" \
                              ...
  1. Ensure you are actually setting the correct Content-Type for your response and it is not just matching as text/html.
  2. Remove the specific Content-Type from this list if you do not want it to be passed through mod_deflate.
Kenrick answered 2/12, 2019 at 16:21 Comment(0)
L
0
$contentLength = -1 ;

The only way worked for me

Larisalarissa answered 3/10, 2023 at 12:46 Comment(1)
You should add some information what '-1' does to the parameter to help the community have a better understanding of your answer.Skelly
B
-1

I had the same problem, and in my case it was solved when I found in some php file included one escape character before <?php tag. Then, the returned by page is bigger than informed in $size = filesize($file); And this cause the error.

Blacktail answered 8/5, 2014 at 14:22 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.