There are meetings on this website and each meeting has a PDF attached showing the meeting minutes. The next meeting that takes place dynamically collects this attached PDF and allows for a download as the previous minutes. This is all working perfectly, however, when clicking the link for the previous minutes it always opens up a save as box. I was wondering how to get this to just display in the browser (assuming the user has a PDF viewer enabled)?
Here is the function from the controller:
public function current_pdf($id = null, $pdf = null) {
$this->loadModel('Document');
$document = $this->Document->find('list', array(
'fields' => array('Document.dir', 'Document.url')
));
$request_pdf = $this->Meeting->read(null, $id);
if ($pdf == 'current') {
$file = $document[$request_pdf['Meeting']['minutes']];
if (!empty($file)) {
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize(WWW_ROOT . 'files/document/url/' . $request_pdf['Meeting']['minutes'] . '/' . $file));
flush(); // this doesn't really matter.
$fp = fopen(WWW_ROOT . 'files/document/url/' . $request_pdf['Meeting']['minutes'] . '/' . $file, "r");
while (!feof($fp)) {
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
//echo WWW_ROOT.'files/document/url/pdf/'.$file; die;
//readfile(WWW_ROOT.'files/document/url/pdf/'.$file);
exit;
}
$this->redirect(array('controller' => 'meetings', 'action' => 'view/' . $id));
} else {
$file = $request_pdf['Meeting']['current_minutes'];
if (!empty($file)) {
//echo filesize(WWW_ROOT.'files/document/url/pdf/'.$file); die;
/* header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . urlencode(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(); */
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
header("Content-Type: application/octet-stream");
header("Content-Type: application/download");
header("Content-Description: File Transfer");
header("Content-Length: " . filesize(WWW_ROOT . 'files/document/url/pdf/' . $file));
flush(); // this doesn't really matter.
$fp = fopen(WWW_ROOT . 'files/document/url/pdf/' . $file, "r");
while (!feof($fp)) {
echo fread($fp, 65536);
flush(); // this is essential for large downloads
}
fclose($fp);
//echo WWW_ROOT.'files/document/url/pdf/'.$file; die;
//readfile(WWW_ROOT.'files/document/url/pdf/'.$file);
exit;
}
$this->redirect(array('controller' => 'meetings', 'action' => 'view/' . $id));
}
}
And here is the link in the view:
<?php echo $this->Html->link(__('Download Previous Minutes'), array('controller' => 'meetings', 'action' => 'current_pdf', $download, 'current')); ?>
I have tried removing the header("Content-Type...") lines of code and changing attachment in header("Content-Disposition: attachment; filename=" . urlencode($file)); to inline. This stopped the save as pop-up but displayed a load of spurious code in the browser instead.
Any help would be greatly appreciated as I'm currently very confused.
I believe this is as simple as removing this line in your code:
header("Content-Disposition: attachment; filename=" . urlencode($file));
This line will server up the file as a download, and not display the content in the browser.
I hope that helps!
Related
Regarding downloading files and defining the headers, I am having trouble assigning a dynamic filename to my files. When using the code below :
header("Content-Disposition: attachment; filename=test.csv");
A test.csv file is generated for download. However if I use this:
header('Content-Disposition: attachment; filename=' . $filename . '.csv');
It generates a .php file instead. Using this method also doesn't pass the Content-Disposition or filename to the header.
Full code:
session_start();
$file =$_SESSION['csvf'];
$filename = $file."_".date("Y-m-d_H-i",time());
header ( "Content-type: text/csv" );
header("Content-Disposition: attachment; filename=test.csv");
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
print($file);
exit ();
What is the correct syntax?
EDIT
Working Code after suggestions
session_start ();
$file = $_SESSION ['csvf'];
$filename =date ( "Y-m-d_H-i", time () );
header ( "Content-type: text/csv" );
header ( "Content-Disposition: attachment; filename=".$filename );
header ( 'Expires: 0' );
header ( 'Cache-Control: must-revalidate' );
header ( 'Pragma: public' );
header ( 'Content-Length: ' . filesize ( $file ) );
print ($file) ;
exit ();
I don't see the path to example.csv specified on your code, you need to give the full path to $file, i.e.:
$mySession = $_SESSION['csvf'];
//since $_SESSION['csvf'] contains the actual data you cannot use it for filename
$filename = date("Y-m-d_H-i",time()).".csv";
//write $mySession contents to file. Make sure this folder is writable
file_put_contents("/home/site/csvfolder/$filename", $mySession);
$file = "/home/site/csvfolder/$filename";
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename='.$filename);
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
Please Use Like as follows,I am using this for me.
header("Content-Type: application/vnd.ms-excel; charset=utf-8");
header("Content-Disposition: attachment; filename=".$fileName);
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
In place of application/vnd.ms-excel use your file format.It is for Microsoft Excel.
Try with this:
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename=test.csv');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
You can see more about download files with PHP here:
http://php.net/manual/en/function.readfile.php
Try With Below code , it's work for me
$file =$_SESSION['csvf'];
$filename = $file."_".date("Y-m-d_H-i",time()).".csv";
header ( "Content-type: text/csv" );
header("Content-Disposition: attachment; filename=".$filename);
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
print($file);
exit ();
Below is a snippet for a .zip file with some descriptions on some information that header requires, perhaps a good practice is to get the information and some validations before writing headers.
Another shorter example is also included,
// defines filename, type, path, size and a reference to file (handler)
// to set as values for file header
$filename = $survey_id . '.zip';
// define path to the file to be get file size on the next line
$filepath = [path to file]. '/' . $filename;
// used by 'Content-length'
$filesize = filesize($filepath);
// using fopen to get a file handler, 'r' for read, 'b' for binary (zip file)
$file_pointer = fopen($filepath, 'rb');
// check if file exists
if(is_file($filepath))
{
// valid file?
if($filesize && $file_pointer)
{
// some required header information to describe file, see [docs][1]
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: public");
header("Content-Description: zip file");
header("Content-Type: application/zip");
header("Content-Type: application/force-download");
header("Content-Disposition: attachment; filename=" . $filename);
header("Content-Transfer-Encoding: binary");
header("Content-length: " . $filesize);
fpassthru($file_pointer);
// close
fclose($file_pointer);
}
}
Also, checkout readfile(), a shorter snippet below
<?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;
}
?>
Hope this helps!
Just escape your php properly like so:
header('Content-Disposition: attachment; filename=' . time() . '.export.csv');
This example will put a UNIX timestamp prepended to the file name. Of course you could get crazy with programmatically using variables or inbuilt php functions, but this is just the example.
Here is more of an example. This file name will be produced when running this php code.
2019-05-18-contacts-main-export-by-Garrick.csv
header('Content-Disposition: attachment; filename=' . date("Y-m-d") . '-contacts-main-export-by-' . $uidName . '.csv');
I am trying to download image file in CI but getting error when I open download image file. Need help :(
$file_name = $_GET['file_name'];
$file_path = "./ups_printimages/".$file_name;
if(file_exists($file_path))
{
$this->load->helper('download');
$data = file_get_contents($file_path); // Read the file's contents
$name = 'ups_label.png';
force_download($name, $data);
}
else
{
echo "file does not exist";
}
GOD. Found out the solution :)
if(!file)
{
File doesn't exist, output error
die('file not found');
}
else
{
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');
ob_clean();
flush();
readfile($file);
exit;
}
Use header to force download. Use the code below
$file_name = $_GET['file_name'];
$file_path = "./ups_printimages/".$file_name;
if(file_exists($file_path))
{
header('Content-Type: image/jpeg');
header("Content-Transfer-Encoding: Binary");
header("Content-disposition: attachment; filename=\"" . basename($file_name) . "\"");
readfile($file_path);
}
else
{
echo "file does not exist";
}
Hope this helps yoiu
I'm doing file download with renaming it before. Everything works except size. I can't set file size with
header('Content-Length: ');
even I'm setting it to
header('Content-Length: 15444544545');
it's not working. I'm using PHP codeigniter framework, where is the problem?
EDIT: more code:
$file_data = array(
'originalName' => $post_info['file_info'][0]['original_name'],
'fakeName' => $post_info['file_info'][0]['file_name'],
'modificationId' => $post_info['file_info'][0]['modification_article_id'],
'extension' => end(explode('.', $post_info['file_info'][0]['original_name'])),
'name' => str_replace(".".end(explode('.', $post_info['file_info'][0]['original_name'])), "", $post_info['file_info'][0]['original_name']),
'filesize' => filesize($post_info['file_info'][0]['file_name'])
);
header('Cache-Control: public');
header('Content-Description: File Transfer');
header('Content-Disposition: attachment; filename=' . $file_data['name'] . '.' . $file_data['extension']);
header('Content-Length: ' . filesize(base_url().$file_data['fakeName']));
// Read file
readfile(base_url().$file_data['fakeName']);
//print_r($file_data);
echo "<script>window.close();</script>";
EDIT: Solution
there was a server problem
You can try like this:
$mm_type="application/octet-stream";
header("Cache-Control: public, must-revalidate");
header("Pragma: hack");
header("Content-Type: " . $mm_type);
header("Content-Length: " .(string)(filesize($fullpath)) );
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary\n");
readfile($fullpath);
wrong usage of base_url().
where is your file stored?
maybe you can try the constant FCPATH instead of call function base_url()
and you have the filesize stored in $file_data['filesize']
finally there should not be a line echo "<script>window.close();</script>"; in your php script when the file content was output.
You tried with download_helper?? Sintax: force_download($filename, $data).
Also in your code you're reading file through URL. Use file system path instead.
From controller action:
<?php
public function download()
{
//Your code here...
$filePath = realpath(FCPATH.DIRECTORY_SEPARATOR.'uploads/myfile.pdf'); //FakeName????
force_download($file_data['fakeName'], readfile($filePath));
}
If my solution don't works give me a touch to give you other way.
Note: FCPATH is the front controller path, a public folder of server e.g.(/var/www/CodeIgniter). Other path constants are already defined on index.php (front-controller).
A print of $file_data['fakeName'] will be useful.
If your CodeIgniter version don't have download_helper make your own... refer to CI docs for full explanation. There is the force_download function code:
function force_download($filename = '', $data = '')
{
if ($filename == '' OR $data == '')
{
return FALSE;
}
// Try to determine if the filename includes a file extension.
// We need it in order to set the MIME type
if (FALSE === strpos($filename, '.'))
{
return FALSE;
}
// Grab the file extension
$x = explode('.', $filename);
$extension = end($x);
// Load the mime types
if (defined('ENVIRONMENT') AND is_file(APPPATH.'config/'.ENVIRONMENT.'/mimes.php'))
{
include(APPPATH.'config/'.ENVIRONMENT.'/mimes.php');
}
elseif (is_file(APPPATH.'config/mimes.php'))
{
include(APPPATH.'config/mimes.php');
}
// Set a default mime if we can't find it
if ( ! isset($mimes[$extension]))
{
$mime = 'application/octet-stream';
}
else
{
$mime = (is_array($mimes[$extension])) ? $mimes[$extension][0] : $mimes[$extension];
}
// Generate the server headers
if (strpos($_SERVER['HTTP_USER_AGENT'], "MSIE") !== FALSE)
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header("Content-Transfer-Encoding: binary");
header('Pragma: public');
header("Content-Length: ".strlen($data));
}
else
{
header('Content-Type: "'.$mime.'"');
header('Content-Disposition: attachment; filename="'.$filename.'"');
header("Content-Transfer-Encoding: binary");
header('Expires: 0');
header('Pragma: no-cache');
header("Content-Length: ".strlen($data));
}
exit($data);
}
I am using following code to start downloading but the pop-up for download is not opening. Instead, it shows the binary format of that pdf file. It's working perfectly on local server but not working hosted server.
$file = '../Notes/chapter01.pdf';
if (file_exists($file)) {
header('Content-Description: File Transfer');
// header('Content-Type: application/octet-stream');
header('Cache-Control: public'); // needed for i.e.
header('Content-Type: application/pdf');
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_end_clean();
flush();
readfile($file);
exit;
}
else {
die('Error: File not found.');
}
This code works.
$file = '../Notes/chapter01.pdf';
$mime_type = 'application/pdf';
$filesize = filesize( $file );
header( "Content-type:" . $mime_type );
header( "Content-Length:" . $filesize );
header( "Content-Disposition: attachment; filename=" . $file );
header( "Cache-Control: private, max-age=15" );
#readfile( $file );
Hope this helps.
I am trying to send a PDF file. Here is the code that is executing:
$file_path = '/path/to/file/filename.pdf'
$file_name = 'filename.pdf'
header("X-Sendfile: $file_path");
header("Content-type: application/octet-stream");
header("Content-Disposition: attachment; filename='$filename'");
readfile($file_path):
whenever I download the file directly, it is fine. however when I try to download the file via this script, a file downloads that cannot be opened. my pdf reader tells me it cannot open a file of type 'text/plain'. I also tried setting the Content-type to application/pdf , but I get the same errors. What am I doing wrong here?
Have you tried this?
$file = '/path/to/file/filename.pdf';
header('Content-Disposition: attachment; filename="'. basename($file) . '"');
header('Content-Length: ' . filesize($file));
readfile($file);
Using readfile() also eliminates any memory issues you might encounter.
try the code below.
header("Content-Type: application/octet-stream");
$file = "filename.pdf";
header("Content-Disposition: attachment; filename=" . urlencode($file));
header("Content-Type: application/force-download");
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)
If the above one does not help you try the below
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header("Content-Type: application/force-download");
header('Content-Disposition: attachment; filename=' . urlencode(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;
Don't for get to set the file path $file_path as required.