I have code to serve requested files in PHP. It's testing code, so input is not validated. (By the way, how to correctly sanitize this kind of input...)
$upload_dir = "/media/usb/dir";
$filename = $_GET['filename'];
$mimetype = $_GET['mime'];
$path = $upload_dir . $filename;
header('Content-Description: File Transfer');
header("Content-Type: ".$mimetype );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($path));
header("X-Sendfile: \"$path\"");
echo readfile($path);
But size of file in bytes is appended to each file.
For example simple txt like this:
myfile
Will become this:
myfile6
How to get rid of this behaviour?
I'm getting textfile like this:
download.php?mime=text/plain&filename=my-file.txt
readfile() returns the size of the file. You can add # to the beginning of the function to remove the error reporting. echo #readfile($path); should display only the filename.
Related
While writing a PHP-Script, im stuck at an issue i cant resolve.
The PHP-Script consist in letting a user download a .mp4 file. The download works without any issues but the file downloaded can not be played.
Heres the code:
<?php
$filepath = "/www/servermedia/technounion.mp4";
$filename = basename($filepath);
header("Content-type: video/mp4");
header("Content-Disposition: attachment; filename=.$filename");
readfile($filename);
exit;
?>
After the .mp4 file gets downloaded, it cannot be played.
It looks like this:
The error message means that Windows Media Player cannot play back the file because probably the player doesnt support the codec. I already tried with VLC but it does not work either.
EDIT:
Comparing both file sizes, the downloaded file is only a couple bytes large instead of the 3,73 MB of the file on the server
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.
Is the downloaded file the exact same filesize?
Does the content type exist in your webserver?
header("Content-Type: video/mp4"); Note capital 'T' for type.
This maybe worth testing with to see you can serve the file content inline:
http://www.phpmind.com/blog/2016/10/how-to-use-php-to-output-an-mp4-video/
I have gone through all articles on Stack Overflow and can't fix my issue. I am using following code:
$file = $_GET['url'];
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
The above mention code is downloading the file from the directly above the root and Yes it is downloading a PDF file but the file is only of 1KB size and not the original size. The $_GET['url'] is receiving ../dir/dir/filename.pdf in it. the filename is space in it as well. For security reason I cannot share the file name.
Please let me know where am I going wrong.
Please make sure you are using the web server path to access the file - for instance your path could be: /home/yourusername/public/sitename/downloads/<filename>, you should check first - to help you can run this at the top of your PHP script to find out the full path for the current script:
echo '<pre>FILE PATH: '.print_r(__FILE__, true).'</pre>';
die();
Only send the filename with the url using urlencode() and on the receiving PHP script use urldecode() to handle any character encoding issues.
See here: http://php.net/manual/en/function.urlencode.php
and here: http://php.net/manual/en/function.urldecode.php
So where you create your url:
Download File
And in your php script:
$file_base_path = '/home/yourusername/public/sitename/downloads/';
$file = urldecode($_GET['url']);
$file = $file_base_path . $file;
$file = $_GET['url'];
if (file_exists($file))
{
if (FALSE!== ($handler = fopen($file, 'r')))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Content-Transfer-Encoding: chunked'); //changed to chunked
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Pragma: public');
//header('Content-Length: ' . filesize($file)); //Remove
//Send the content in chunks
while(false !== ($chunk = fread($handler,4096)))
{
echo $chunk;
}
}
exit;
}
echo "<h1>Content error</h1><p>The file does not exist!</p>";
I hope this helps you!
I'm trying to setup a backup system that will perform a backup, compress the file and make it downloadable from a browser. The file downloads properly but when I try to uncompress it I get:
unxz: backup_2015-08-12.txz: File format not recognized
There is a backup script that will output
/tmp/agribackup.txz
The PHP script is as follows:
<?php
// Create the agribackup.txz file
$e = shell_exec("/usr/local/bin/agribackup.sh");
$file = '/tmp/agribackup.txz';
if(file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/xz');
header('Content-Disposition: attachment; filename=backup_'.date("Y-m-d") . '.txz');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
I think you are using the wrong Content-Type. Refering to 'http://tukaani.org/xz/xz-file-format.txt', the correct MIME-type is 'application/x-xz'.
Hi I am trying to allow download a demo file which is related to a product. my code is like this
if(isset($_POST['submit'])){
$root = $_SERVER['DOCUMENT_ROOT'];
$path = "/download/";
$path = $root.$path;
$filename = $demo;
$file = $path.$filename;
header('Content-Type: application/force-download');
header("Content-Transfer-Encoding: Binary");
header("Content-Disposition: attachment; filename=\"".basename($file)."\";" );
header("Content-Length: ".filesize($file));
readfile($file);
}
I am able to get file name which is associated with the product by
$demo
After user submits his information, download will start automatically. Now this is downloading a non existing file or corrupted file with the proper file name. please help
<?php
$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, post-check=0, pre-check=0');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
?>
As you can see Content type is application/octet-steam meaning file is byte by byte encoded. Also the cache headers are set. Then headers are forcefully sent by ob_clean();flush(); and then the file is read.
The file_exists is there to ensure that given file exists. You should also try not not thrust user input as they could easy write names for your php codes and download EACH file. And with ../ in names of the files, even your documents or system files and so on.
The code below is for two purposes
1) I save a text file on my server in a folder named "backup_db" its working fine mean when I open that text file it contain all the data
2) At the same time i also make this file downloadable for a user so that he could download it for himself and could save it on his hard disk and according to my wish its downloading but unfortunately the .txt file saved on my hard disk is, when open its empty and i don't know why please help me out
//save file
$handle = fopen('backup_db/db-backup-'.date('d-m-Y_H-i-s').'-'.(md5(implode(',',$tables))).'.txt','w+');
$rr = fwrite($handle,$re);
//fclose($handle);
$ww = "db_backup".$rr.".txt";
//$handle = "";
header('Content-Disposition: attachment; filename=' . urlencode($ww));
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
header('Content-Description: File Transfer');}}
You only set the HTTP header but did not write the file into the response body. Use either fpassthru() or readfile() to write the content of the file directly to the response.
Sample (taken from php.net)
<?php
$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));
flush();
readfile($file);
exit;
}
?>
BTW:
Settings the same header multiple times simply overwrites the value set before unless you set the second parameter of header() to false.
Your code
header('Content-Type: application/force-download');
header('Content-Type: application/octet-stream');
header('Content-Type: application/download');
results in the following header:
Content-Type: application/download
Sending a file namein the header just gives the user a suggested filename. Try echoing out the contents of the file.
You should add
header("Content-Length: $size")
where $size is size of yout file in bytes.
Check this
ex :
$filename = urlencode($fileName); //download.txt
header("Content-Disposition: attachment; filename=\"" . $filename. "\";" );