PHP readfile() adding extra bytes to downloaded file
Remove the last ?>
and check that your opening tag is on the very first line, at the very first character of your scripts. PHP files do not have to end with end tags. The reason why your downloaded files contain a (or more) \r\n
is because PHP will directly echo (output) anything outside of <?php ?>
. Usually, if you script does not echo HTML, you will omit the closing PHP tag as it is not mandatory and, IMO, yields more trouble than anything else.
** Edit **
If you read the PHP manual for readfile
, you have a useful example, pretty much the code you have in your question, less two lines of code :
@apache_setenv('no-gzip', 1);
header("Content-length: " . filesize('upload/' . $_GET['name']));
header('Content-type: application/zip');
//header("Content-Disposition: attachment; filename=\"{$_GET['name']}\" ");
header("Content-Disposition: attachment; filename={$_GET['name']}");
header('Content-Transfer-Encoding: binary');
// add these two lines
ob_clean(); // discard any data in the output buffer (if possible)
flush(); // flush headers (if possible)
readfile('upload/' . $_GET['name']);
exit();
If you still have a problem after that, then the problem might not be with your PHP code.
PHP: Downloaded binary file gets an additional byte (0x0a) at the end
You most likely have an extra blank line after the closing ?>
, which is being echoed with the data. The closing ?>
is always optional at the end of a PHP file. Leaving it out is a good practice to prevent this sort of problem.
The reason the Content-Length changes is because the HTTP server (or PHP?) is ignoring it and adding a new one to match the actual data response before it gets sent it to the browser, so I think you can just leave that out. (If you do manage to send data with the wrong Content-Length, I've found browsers can act very weird.)
How to add extra data at the end of downloading content in PHP
Store your extra bytes in a file,variable,db or etc , and echo it after read file function
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
readfile("extra_filename.ext");
/*
//or use this
$extra_bytes = "store extra bytes here";
echo $extra_bytes;
*/
exit;
}
readfile returns additional digit
http://php.net/manual/en/function.readfile.php
readfile()
automatically echos the file's contents, so you don't need to use echo
.
readfile()
also returns an int and that's the 3 you are seeing.
Change your code to this.
<html>
<body>
<h1>My first PHP page</h1>
<?php
readfile("/home/pi/test/hx711py/export.txt", "r");
?>
</body>
</html>
Prepend bytes to file before download
It's possible, of course.
Now this depends on how you are serving the files. If you link directly to the files you will have to create a rewrite rule in your web server, that will pass the requested file to your PHP script[1]. The script will then output your "prependtext" along with the contents of the file. Don't forget to add appropriate HTTP headers[2]!
If you are already serving the files trough a PHP script then you jut need to output your "prependtext" before you output the contents of the file.
Remarks:
[1] To do so memory efficient with large files, use readfile()
[2] For text files the most important header is Content-type: text/plain
(also see documentation for header()
and readfile()
)
(PHP) Problem with filename after downloading it
Your code is not well-formed, you miss to escape double-quotes by adding single-quotes as I done here, please test my answer.
<?php
$filepath = "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="' . $filename . '"');
readfile($filename);
exit;
?>
But I suggest a more complex way:
<?php
$filepath = $_SERVER['DOCUMENT_ROOT'] . "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header('Content-Type: video/mp4');
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Content-Transfer-Encoding: binary');
header('Connection: Keep-Alive');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . sprintf("%u", filesize($filepath)));
set_time_limit(0);
$fh = fopen($filepath, "rb");
while (!feof($fh)) {
echo fgets($fh);
ob_flush();
flush();
}
fclose($fh);
exit;
?>
$_SERVER['DOCUMENT_ROOT']
is useful to get the full path from the server
set_time_limit(0)
is useful to avoid any timeout during download
fgets()
is useful for reading large files
ob_flush()
and flush()
assure that there is not other output in the buffer
I hope this helps.
Related Topics
PHP $_Server['Remote_Addr'] Shows Ipv6
Symfony: How to Refresh the Authenticated User from the Database
Get/Set Dpi with PHP Gd/Imagick
How to Verify the Requesting Server in PHP
In PHP, How to Generate a Big Pseudo-Random Number
How to Integrate PHPmailer with Codeigniter 3
Setting Variables on Constructor VS on the Class Definition
How to Disable or Encrypt "View Source" for My Site
How to Convert an Integer to an Array in PHP
Count of Duplicate Elements in an Array in PHP
How to Recursively Obtain the "Parent Id" of Rows in This MySQL Table
What Is the ASP.NET Equivalent to PHP's Echo
Getting All $_Post from Multiple Select Value
How to Make My PHP Script Run at a Certain Time Everyday
PHP "Header (Location)" Inside Iframe, to Load in _Top Location
Discount for Certain Category Based on Total Number of Products