I'm preparing a CSV file to download.
I know I'm nearly there as the link at the end of this code produces the right result. What I need to do and don't understand why it doesn't work, is create the downloaded file programmtically (using an example from http://php.net/manual/en/function.readfile.php). If I omit ob_start() I get "Headers already sent" error, if I include them nothing happens.
What am I doing wrong?
$filename = 'export.csv';
$data = fopen($filename, 'w');
while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
fputcsv($data, $row);
}
fclose($data);
if (file_exists($filename)) {
ob_start();
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($filename).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($filename));
readfile($filename);
ob_get_clean();
}
The output file is produced fine, I can see it on the server and it downloads using a link as valid CSV correctly produced. It's purely prompting the download that is not happening.
Related
I can't download files that already uploaded in my website, for example :
I already uploaded a video file with 800mb file size and it is okay, the file is save to my directory in the File folder, then I want to download that file again, but as soon as I download the file, I will always got 1kb file not the exact size of the file, and when I play it, nothing happen
this is my code:
<?php
include 'db.php';
if(isset($_REQUEST['name']))
{
$var =$_REQUEST['name'];
$dir = "../files/";
$file = $dir . $var;
if(file_exists($file))
{
header('Content-Description: File Transfer');
header('Content-Type: video');
header('Content-Disposition: attachment;
filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
mysqli_close($conn);
exit();
}
else{
echo "File not found";
}
}
?>
Yeah, I had the same problem too. After searching alot on the internet, I found out that the problem is related to output buffering. The following code solved my problem.
<?php
$file = $_GET['file'];
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_end_clean(); //adding this line solves my problem
readfile($file);
exit;
?>
The code ob_end_clean() basically runs grabs everything in the buffer, then erases the buffer, and turns off output buffering.
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 trying to export few data in CSV file. Though the file is successfully written but it is not downloading instead is being read by browser. $csvarray is data array and fputcsv2 is function similar to PHP default fputcsv function
$output = fopen("php://output",'w') or die("Can't open php://output");
rewind( $output );
foreach($csvarray as $product) {
fputcsv2($output, $product,',',' ');
}
header("Content-type: text/csv");
header('Content-Disposition: attachment; filename="export.csv"');
readfile ($output);
exit();
Finally the issue got resolved, may be helpful for somebody,
when I generate the data array before dumping it into the CSV file I printed array using $print_r with <pre> ... </pre> tag. though I remove $print_r but <pre> ... </pre> tag was still there preventing file to download. As soon as I remove this tag file is now downloaded.
First example in the readfile() documentation should help you: http://php.net/manual/en/function.readfile.php
Example #1 Forcing a download using readfile()
<?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('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
I have created a beginner program to forcefully download file from unix box to windows through browser, it is not throwing any error but shows nothing on browser just a blank page.
PHP version- 5.2.13
Apache-2.0
Unix Box- HP-UX 11.11 (old version latest is 11.31)
local PC- windows XP Prof.
Browser- IE 7, Mozilla.
Below is my code (this code resides on unix box):
<?php
ob_start();
$file = '/opt/hpws/apache/htdocs/barn/file2';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream;charset=utf-8');
header('Content-Disposition: attachment; filename=$file');
header('Content-Transfer-Encoding: binary');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
?>
This line had quotation marks missing:
header('Content-Disposition: attachment; filename=$file');
and in trying to use that line of code, the browser would prompt to save the file as $file.
The line of code should read as:
header('Content-Disposition: attachment; filename="'.basename($file).'"');
The following (tested with a binary file) with file inside the same folder as executed code.
NOTE: You could use header("Content-Type: application/text"); if it's an ASCII file.
<?php
ob_start();
$file = 'file.zip';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream;charset=utf-8');
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));
readfile($file);
exit;
}
?>
Okay, let's add some checks and debugging.
<?php
$file = '/opt/hpws/apache/htdocs/barn/file2';
if (!file_exists($file)) {
die("The file does not exist");
}
if (!is_file($file)) {
die("Not a file"); // Worry about symlinks later
}
if (!is_readable($file)) {
die("The file is not readable");
}
die("DEBUG: Okay, will send the file -- remove this line and retry");
$name = basename($file); // Or anything else
header('Content-Type: application/octet-stream');
header("Content-Disposition: attachment; filename=\"{$name}\"");
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit();
?>
If this does not work, it should at least tell you why. Also, on the first run, the one when it will still not download the file but only tell you that it will, check that the page does not contain anything else except that one line. Otherwise, you're setting yourself up for a fall; if not this once, as soon as you have to send a file larger than your output buffers, or too many files for your system memory.
In my code I am creating a file with fgetcsv. I download it and open the file but all the html from my page is included with the csv file. Is there anyway I can just have the data I want to output from the file and not the extra html. my function for creating the csv is below
function makefile()
{
header('Content-type: text/csv');
header("Cache-Control: no-store, no-cache");
header("Content-Disposition: attachment;filename=file.csv");
$this->filepointer = fopen('php://output', 'a');
for($count=0;$count < count($this->alldata);$count++)
{
fputcsv($this->filepointer, $this->alldata[$count]);
}
fclose($this->filepointer);
}
also I was wondering if i use $this->filepointer = fopen('file.csv', 'w') will the file still be populated with the html. as I dont have to have the file downloading I was just using it to check if the file was being created in the correct format. thanks again
You can try the below code. You need to add read_file at the end after setting some header as below.
<?php
if(isset($_GET['link']))
{
$var_1 = $_GET['link'];
$file = $var_1;
if (file_exists($file))
{
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename='.basename($file));
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
ob_clean();
flush();
readfile($file);
exit;
}
} //- the missing closing brace
?>
use ob_end_clean() ; before writing the file