Here's what I'm trying to do. I have a series of reports that they also want to be able to download as comma delimited text files. I've read over a bunch of pages where people say simply echo out the results rather than creating a file, but when I try that it just outputs to the page they are on.
I have this in the form of each report
Export File<input type="checkbox" name="export" value="1" />
So on the post I can check if they are trying to export the file. If they are I was trying to do this:
if($_POST['export'] == '1')
{
$filename = date("Instructors by DOB - ".$month) . '.txt';
$content = "";
# Titlte of the CSV
$content = "Name,Address,City,State,Zip,DOB\n";
for($i=0;$i<count($instructors);$i++)
$content .= ""; //fill content
fwrite($filename, $content);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
}
Basically the page refreshes, but no file is pushed for download. Can anyone point out what I'm missing?
EDIT
I think I wasn't entirely clear. This is not on a page that only creates and downloads the file, this is on a page that is also displaying the report. So when I put an exit(); after the readfile the rest of the page loads blank. I need to display the report on this page as well. I think this could also have to do with why it's not download, because this page has already sent header information.
I overlooked the way you are writing out the contents before asking you to try closing the file.
Check the fwrite manual here: http://php.net/manual/en/function.fwrite.php
What you need to do is:
$filename = "yourfile.txt";
#...
$f = fopen($filename, 'w');
fwrite($f, $content);
fclose($f);
and after closing the file, you can now safely send it across for download.
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
There are a couple of things:
You really dont need to set the content-type as application/octet-stream. Why not set a more real type as text/plain?
I really dont understand how you want to use the date functionality. please refer to the manual here: http://php.net/manual/en/function.date.php
As correctly pointed out by #nickb, you must exit the script after doing the readfile(..)
Related
I'm learning PHP so this is the question for education purposes. Since I can't find an answer in tutorials I use, would be nice from you to make it clear for me.
So, imagine we have a file "text.txt" and content is:
"Hello World!"
The following PHP script:
<?php
echo readfile("text.txt");
?>
Will output "Hello World!12" - I can't think of any cases when such an output can be useful, but I found that if I don't want to see the file length at the end, I've to omit "echo":
<?php
readfile("text.txt");
?>
The output will be "Hello World!". This is a way better, but manual says: "Returns the number of bytes read from the file.", so my question is - How am I supposed to get the file length using the readfile() function? According to my logic it "returns" the file content but I feel like I didn't get something right. Please help me to figure this out.
So you want to read the size of a file using readfile()? Sure, but this function also outputs the file. No biggie, we have something we can use in this situation: output buffering.
<?php
ob_start();
$length = readfile("text.txt");
// the content of the file isn't lost as well, and you can manipulate it
$content = ob_get_clean();
echo $length;
?>
readfile is not used to get file size or file content the way you write. It is typically used to send a file to the client. For example, suppose that you have created a pdf file in your web application after the client submit a form or clicked some link. Sometimes you can direct them to the file directly, but sometimes you dont want that for some reasons(security etc.). This way you can do this:
How it is ment to be used.
$filepath = "../files/test.pdf";
header("Content-Description: File Transfer");
header("Content-Type: application/pdf; charset=UTF-8");
header("Content-Disposition: inline; filename='test.pdf'");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($filepath));
readfile($filepath);
exit;
An example for which you may use it.
$filepath = "../files/test.pdf";
ob_start();
$filesize = readfile($filepath);
$content = ob_get_clean();
header("Content-Description: File Transfer");
header("Content-Type: application/pdf; charset=UTF-8");
header("Content-Disposition: inline; filename='test.pdf'");
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . $filesize );
echo $content;
exit;
So, here you output the file content in addition to the correct headers so that the browser will identify it as a pdf file and open it.
I am trying to get the browser to prompt the user to download a file. However, after having tried several methods from stack overflow and around the Internet, for some reason all are silently failing. Is it the case that this just isn't possible in modern browsers?
I'm simply wanting the user to download a text (.txt) file from the server. I've tried this code below (and more) to no avail:
header('Content-disposition: attachment; filename=newfile.txt');
header('Content-type: text/plain');
readfile('newfile.txt');
.
header("Content-Type: application/octet-stream");
$file = $_GET["file"] .".txt";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize($file));
flush(); // this doesn't really matter.
$fp = fopen($file, "r");
while (!feof($fp))
{
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
I have tried the examples from PHP.NET (none of which are working for me):
http://php.net/manual/en/function.readfile.php
I have the correct permissions set, the file exists and is_readable. I'm now left scratching my head as to why this isn't working. Any help would be great.
I have one solution for you.
Lets assume download.php is the file that downloads the file.
So when the user clicks on the link to download show a confirm dialog, if the user selects yes then re direct the user to download.php or else download will not occur some browsers like chrome starts the download without asking users if they like to download a file or not.
I have a Laravel web app that generates a formatted .txt and then has the browser download it, and refreshing the form after everything is done, the .txt is generated correctly but I'm not getting a redirect, how can I make a redirect and also have the file downloaded? I wouldn't mind if it needs to be changed to a save window and have the user select the location, but otherwise it can't save directly to the server.
Here is the code that generates the .txt in my controller.
$filename = "Payments-".date('d-M-Y').".txt";
$f = fopen($filename, 'w');
fwrite($f, $header.PHP_EOL.$payments);
fclose($f);
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Length: ". filesize("$filename").";");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/octet-stream; ");
header("Content-Transfer-Encoding: binary");
readfile($filename);
//exit;
return view('index')->with('date', $date->format('d-M-y'));
For redirect:
Use Laravel redirect helper:
return redirect('some-url')->with('date', $date->format('d-M-y'));
For download file use enter link description here this:
return response()->download($pathToFile);
I have a zip files that I want users to be able to download. The trick is I don't want the users to see what the url is and I don't want to download the file to my server.
So I want users to click a link like this:
http://example.com/download/4
which server-side accesses my S3 bucket with this url:
https://s3.amazonaws.com/my-bucket/uploads/4.zip
I've tried cURL, using S3 methods, and various headers() in my download($file_id) function but can't get this to work. This has to be easy, right?
Your right, its quite easy. Probably you will have to write something like this:
$path = '/my-bucket/uploads/4.zip'; // the file made available for download via this PHP file
$mm_type="application/x-compressed"; // modify accordingly to the file type of $path, but in most cases no need to do so
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($path)) );
header('Content-Disposition: attachment; filename="'.basename($path).'"');
header("Content-Transfer-Encoding: binary\n");
readfile($path); // outputs the content of the file
exit();
You set various headers to make your user download the .zip. Afterwards you put your file into the output buffer with readfile() Afterwards you end your script with exit() for security's sake. This should work for you! Remember to change the path to your file.
Thanks #Xatenev for the help. This is actually what worked for me:
$path = '/my-bucket/uploads/4.zip'; // the file made available for download via this PHP file
$mm_type="application/zip"; // modify accordingly to the file type of $path, but in most cases no need to do so
header("Content-Type: " . $mm_type);
header('Content-Disposition: attachment; filename="'.basename($path).'"');
readfile($path); // outputs the content of the file
exit();
I can't seem to figure this out and I know it's something simple. I am building the back-end to a very basic content management system. For this specific piece, I am just trying to create a PHP link that allows for a file (the client's CV) to be downloaded.
MY PROBLEM:
When the link to download the file is clicked, instead of the browser prompting you to choose a local directory to save the file to - it simply displays the file and a bunch of symbols before and after the document's contents (I am assuming this is the file's opening and closing exif data for an application to decipher).
How could I go about forcing the browser to prompt the user for a "Save As..." box?
<?php
require("connect.php");
$query = "SELECT * FROM kb_info LIMIT 1";
$result = mysql_query($query, $link);
while ($row = mysql_fetch_array($result)) {
$file_extension = end(explode(".", $row["extension"]));
if ($file_extension == doc) {
header('Content-disposition: attachment; filename='.$row["extension"]);
header('Content-type: application/doc');
header ("Content-Length: ".filesize($row["extension"]));
readfile($row["extension"]);
exit;
}
if ($file_extension == docx) {
header('Content-disposition: attachment; filename='.$row["extension"]);
header('Content-type: application/docx');
header ("Content-Length: ".filesize($row["extension"]));
readfile($row["extension"]);
exit;
}
if ($file_extension == pdf) {
header('Content-disposition: attachment; filename='.$row["extension"]);
header('Content-type: application/pdf');
header ("Content-Length: ".filesize($row["extension"]));
readfile($row["extension"]);
exit;
}
}
?>
Many thanks,
Joshie
I think the problem can be that there is some whitespace somewhere in the PHP files, which causes that the headers are not sent correctly and therefore you see the whole output.
I would suggest the followings steps:
check the "connect.php" and look for empty lines/spaces at the begining/ending of the file and remove them
adapt you php files that way, that you leave out the ending tag ?> at the end of the file - that way you do not get empty lines at the end of the file
if the above are not enough you need to check your apache and php error log and/or set up error loging, so you see also warnings - that you you would be informed if the headers are not sent correctly or if there is some other error
Headers I use for download:
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-type: application/force-download");
header("Content-Disposition: attachment; filename=".$file);
header("Content-Type: application/octet-stream");
header("Content-Transfer-Encoding: binary");
header("Content-Length: ".$bytes."");