everybody, im running in some issue right now, see for internal situations with the server that i cant control or anything right now i cant use base64 encoded files directly over the website cause when the server delivers content to the browser it has a limit of characters for those tasks and it directly affects base64 encoded files cause of the lenght of those strings, so i made for one system a php script that delivers an already existing base64 pdf files to the client as a downloadable file, and it worked just like this:
$reg = File::find($args->string('id')); //querying the file from database
$filename = $reg->filename; //the original file name
$base64 = $reg->file; //the base64 encoded file
$meta_type = explode(',', $base64) [0]; //getting the meta type of the file
$meta_type = str_replace('data:', '', $meta_type);
$meta_type = str_replace(';base64', '', $meta_type);
$file = explode(',', $base64) [1];
$file = base64_decode($base64); //decoding the base64 string
header('Content-Description: File Transfer');
header('Content-Type: ' . $meta_type);
header('Content-Disposition: attachment; filename="' . $filename . '"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . (strlen($file)));
echo $file;
this worked just fine when i use pdf files but when i try to use it on some 'xlsx' files it seem to work, it download the file, the filesize and all seem to match the original, but excel cant open the file, does anybody have an idea of what im i missing here?? :)
I am pretty sure, its happening, because you are not exiting your function and it continues to fill up buffers. You have to stop the script immediatelly after your stream is ready, clean the buffer and exit.
If its a valid Excel file, all you have to do is:
header('Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
header('Cache-Control: must-revalidate');
header('Expires: 0');
header('Pragma: public');
header('Content-Disposition: attachment; filename="' . $filename . '"');
if (ob_get_contents() || ob_get_length()) {
ob_end_clean(); //or ob_end_flush();
}
exit();
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 am not able to open the file after the download.
It says the the file has been corrupted.
I guess i have used all the required headers fine.
In chrome it shows error like:
chrome resource interpreted as document but transferred with mime type application/octet-stream
In Firefox no error msg.
if (isset($_GET['file']) && basename($_GET['file']) == $_GET['file']) {
$filename = $_GET['file'];
} else {
$filename = NULL;
}
$err = 'Sorry, the file you are requesting is unavailable.';
if ($filename) {
// define the path to your download folder plus assign the file name
$path = '/wp-content/uploads/'. $filename;
// check that file exists and is readable
if (file_exists($path)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'. basename($path) . '"');
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($path));
ob_end_clean();
flush();
readfile($path);
exit;
}
}
download: getting downloaded from ftp folder.
None of the formats are opening.
.txt is getting opened.
Let me know if i am in wrong direction.
Inserting into table:
echo "<tr><a href='?file=". $row["FileupName"]."'>".$row["FileupName"]."</td></tr>";
readfile('$path') is your issue, it should be readfile($path) (with no quotes)
In PHP, variables are only evaluated in strings if the string is defined in double quotes ". Effectively you're downloading a file where the contents is the literal string '$path', with an incorrect filesize.
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.
I used php output buffering earlier in order to create csv file from database, because i didn't want to create an existing file, just wanted to make content downloadable.
CSV is text-based file, so its easy to create this way, you set the header and flush the text content. But! What if, I want to create an exe from hex data? (The project is: I have an existing exe file and I want that users can write something inside a HTML textbox and I convert that to hex and exchange the old text to the new one)
Thanks.
Use following code to download exe file by reading from hard disk.
<?php
$file = 'test.exe';
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);
exit;
}
If you want to replace part of binary file, for example from 100th byte to 200th byte you could use substr() and str_pad():
$binFile = file_get_contents('/pathto/exec/file.exec');
$replacedBinFile = substr($binFile, 0, 100) . str_pad(substr($_POST['text'], 0, 100), 100, "\x00") . substr($binFile, 200);
file_put_contents('/pathto/exec/file_replaced.exec', $replacedBinFile);