By going through the Codeigniter documentation, I am using the following code to force download files from my server.
function download($file_id){
$file = $this->uploadmodel->getById($file_id); //getting all the file details
//for $file_id (all details are stored in DB)
$data = file_get_contents($file->full_path); // Read the file's contents
$name = $file->file_name;;
force_download($name, $data);
}
The code is working file for images, but when it comes with the case of PDF files, it is not working. I have not tested it for all file extensions, but since it is not working for PDF, it might not work for other various file types.
Any solution?
I've had similar problems. I think the problem resides in certain mime's and headers sent to the browser(s). I've end up using the code I found here http://taggedzi.com/articles/display/forcing-downloads-through-codeigniter. Use the function below instead of force_download. It has worked for me so far.
function _push_file($path, $name)
{
// make sure it's a file before doing anything!
if(is_file($path))
{
// required for IE
if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }
// get the file mime type using the file extension
$this->load->helper('file');
$mime = get_mime_by_extension($path);
// Build the headers to push out the file properly.
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($path)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: '.$mime); // Add the mime type from Code igniter.
header('Content-Disposition: attachment; filename="'.basename($name).'"'); // Add the file name
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($path)); // provide file size
header('Connection: close');
readfile($path); // push it out
exit();
}
}
Hope it helps.
It is working for .pdfs also.
Check the path to the file - that might be the problem.
I, too, had that problem, but when I corrected the path to the file, it worked perfectly.
The following is how I wrote the code:
if($src == "xyyx")
{
$pth = file_get_contents(base_url()."path/to/the/file.pdf");
$nme = "sample_file.pdf";
force_download($nme, $pth);
}
Try this, I think its best practice for that problem.
function download($file_id)
{
$this->load->helper('file'); // Load file helper
$file = $this->uploadmodel->getById($file_id); //Get file by id
$data = read_file($file->full_path); // Use file helper to read the file's
$name = $file->file_name;;
force_download($name, $data);
}
Related
I am trying to create a simple digital store web application using codeigniter.
I would like to use the force download helper function so that the real url of the file will not be known by the user.
I tried following the documentation in the codeignter - it works but the file get corrupted.
Here is my code
//* Get the website name
$site = $this->Settings_model->getApllicationInfo();
$sitename = $site->set_site_name;
//* Prepare file for downloading
$filename = $sitename.'-'.$item_info->item_id.'-'.$item_info->item_name;
$locate = './static/files/zips/'.$file;
force_download($locate, $filename);
It downloads the file but it get broken please help me or give me any other suggestion I can use.
Use below function to download the file
function auto_download($path, $name) {
if(is_file($path)) {
if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }
$this->load->helper('file');
$mime = get_mime_by_extension($path);
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($path)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.basename($name).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($path));
header('Connection: close');
readfile($path);
exit();
}
}
I hope you are using file extension on the filename you supply for the first argument to force_download(). Because Codeigniter uses MIME-type. I hope it will work for you
public function ExportCSV(){
$this->load->dbutil();
$this->load->helper('file');
$this->load->helper('download');
$delimiter = ",";
$newline = "\r\n";
$slash = "∕";
$filename = "testnaja.csv";
$query = "select * from student where room_id = 011";
$result = $this->db->query($query);
$data = $this->dbutil->csv_from_result($result, $delimiter, $newline);
force_download($filename, $data);
}
I want to generate excel file exporting data from my table to it.
The output in .xls and .csv
In csv output is:
Please help. Thanks.
Change your force_download from
force_download($filename, $data);
To this:
force_download($filename, "\xEF\xBB\xBF" . $data);
which makes the output UTF-8 + BOM so it's recognized by MS Excel
I don't know if I understood you correctly, but if your problem is that you'd like Excel to recognize your CSV file as being UTF-8 encoded, you'll have to add a UTF-8 BOM to your file. Just prepend your CSV output with
chr(239) . chr(187) . chr(191) // xEF xBB xBF
For example:
$data = chr(239) . chr(187) . chr(191) . $this->dbutil->csv_from_result($result, $delimiter, $newline);
If your problem is about forcing a download, perhaps https://stackoverflow.com/a/33593363/11354 is going to help.
To setup codeigniter to download CSV format, use the following code.
function _push_file($path, $name)
{
// make sure it's a file before doing anything!
if(is_file($path))
{
// required for IE
if(ini_get('zlib.output_compression')) { ini_set('zlib.output_compression', 'Off'); }
// get the file mime type using the file extension
$this->load->helper('file');
$mime = get_mime_by_extension($path);
// Build the headers to push out the file properly.
header('Pragma: public'); // required
header('Expires: 0'); // no cache
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime ($path)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: '.$mime); // Add the mime type from Code igniter.
header('Content-Disposition: attachment; filename="'.basename($name).'"'); // Add the file name
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($path)); // provide file size
header('Connection: close');
readfile($path); // push it out
exit();
}
Duplicate from : Codeigniter Force download files
and also from : Download csv from codeigniter mysql
This php file is supposed to:
receive a piece of information from a form on a different page
use this information to create an array of file paths to add to a zip file
create a dynamically named zip file using a class that's included.
force the download of the newly created zip file
numbers 1-3 are working flawlessly.
The page even forces the download of a zip file that is correctly named and is the right size, but when I try to open it, it says the file is invalid. I've seen similar problems in searches, but I have yet to find a solution.
If i enter the direct URL for the newly created zip into the browser, the file downloads and opens perfectly. As a matter of fact, my temporary fix was creating a dynamic direct link to the files :/
I should probably mention that this is hosted on the go daddy economy plan.
<?php
error_reporting(0);
include "gavScripts/connect_to_mysql.php";
require_once 'Zipper.php';
// prepare the file paths to add to the zip file and find the job/client name (for naming the zip folder)
if(isset($_POST['jobName']))
{
$clientID = $_POST['jobName'];
$clientSQL = mysql_query("SELECT clientName FROM job_client WHERE clientID = $clientID");
while($clientRow = mysql_fetch_array($clientSQL))
{
$clientName = $clientRow['clientName'];
}
$zipSQL = mysql_query("SELECT filePath FROM job_expense WHERE clientID = $clientID");
While($zipRow = mysql_fetch_array($zipSQL))
{
$filePaths[] = $zipRow['filePath'];
}
}
//create the zip folder and store the requested files
$zipper = new Zipper();
$zipper->add($filePaths);
$zipper->store('invoices/' . $clientName . '_Invoices.zip');
//download the zip
$fileDownload = 'invoices/' . $clientName . '_Invoices.zip';
$fileName = basename($fileDownload);
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=" . $fileName . "");
header("Content-Length: " . filesize($fileDownload));
readfile($fileDownload);
?>
You may have trailing whitespace at the end of your script which is breaking your zip file. Is there a \r or \n (or both) after the closing ?>? Try removing the closing ?> which is optional anyway.
Try the following:
header('Pragma: public');
header('Expires: 0');
header('Cache-Control: must-revalidate, post-check=0, pre-check=0');
header('Last-Modified: '.gmdate ('D, d M Y H:i:s', filemtime($fileName)).' GMT');
header('Cache-Control: private',false);
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="'.basename($fileName).'"');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.filesize($fileName));
header('Connection: close');
readfile($fileName);
exit();
Might help.
I am working on a project where I get a file stream and write this file to the servers local disk.
I then want PHP to download it but instead it just dumps out the data of the file to the page.
Below is how I am writing the file and trying to tell PHP to download it
$settingsManager = new SettingsManager();
$this->tempWriteLocation = $settingsManager->getSpecificSetting("hddFileWriterLocation");
$downloadUrl = $settingsManager->getSpecificSetting("tempFileUrlDownload") . "/$this->tempFileName";
if (!$this->checkIfDirectoryExists())
{
throw new Exception("Failed to create temp write directory: $this->tempWriteLocation");
}
$filePathAndName = "$this->tempWriteLocation\\$this->tempFileName";
$fh = fopen($filePathAndName, "w");
if (!$fh)
{
throw new Exception("Failed to open file handle for: $filePathAndName. " . error_get_last());
}
fwrite($fh, $this->fileData);
fclose($fh);
//return $downloadUrl;
header('Content-Description: File Transfer');
header('Content-Type: audio/wav');
header('Content-Disposition: attachment; filename='.basename($filePathAndName));
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($filePathAndName));
ob_clean();
flush();
readfile($filePathAndName);
When the above code being run, I get the following output (only a snippet)
RIFF\tWAVELIST2INFOISFT%Aculab Media System Server V2.3.4b11fmt
##fact�sdata�sUU������UUUUUU�UUU��U���UU��UUU�UUUU���UU���UU�����UU
Just so you know the diamonds are actual output I get back, not anything wrong with Stack Overflow displaying something properly.
I've tried setting the content-type to be force-download but doesn't make any difference.
Try this header:
header('Content-type: audio/x-wav', true);
header('Content-Disposition: attachment;filename=wav-filename.wav');
and see if this works. From what I see you have you code formation setup correctly. Fixing the headers should download the file automatically.
If I goto http://site.com/uploads/file.pdf I can retrieve a file.
However, if I have a script such as:
<?php
ini_set('display_errors',1);
error_reporting(E_ALL|E_STRICT);
//require global definitions
require_once("includes/globals.php");
//validate the user before continuing
isValidUser();
$subTitle = "Attachment";
$attachmentPath = "/var/www/html/DEVELOPMENT/serviceNow/selfService/uploads/";
if(isset($_GET['id']) and !empty($_GET['id'])){
//first lookup attachment meta information
$a = new Attachment();
$attachment = $a->get($_GET['id']);
//filename will be original file name with user name.n prepended
$fileName = $attachmentPath.$_SESSION['nameN'].'-'.$attachment->file_name;
//instantiate new attachmentDownload and query for attachment chunks
$a = new AttachmentDownload();
$chunks= $a->getRecords(array('sys_attachment'=>$_GET['id'], '__order_by'=>'position'));
$fh = fopen($fileName.'.gz','w');
// read and base64 encode file contents
foreach($chunks as $chunk){
fwrite($fh, base64_decode($chunk->data));
}
fclose($fh);
//open up filename for writing
$fh = fopen($fileName,'w');
//open up filename.gz for extraction
$zd = gzopen($fileName.'.gz', "r");
//iterate over file and write contents
while (!feof($zd)) {
fwrite($fh, gzread($zd, 60*57));
}
fclose($fh);
gzclose($zd);
unlink($fileName.'.gz');
$info = pathinfo($fileName);
header('Content-Description: File Transfer');
header('Content-Type: '.Mimetypes::get($info['extension']));
header('Content-Disposition: attachment; filename=' . basename($fileName));
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($fileName));
ob_clean();
flush();
readfile($fileName);
exit();
}else{
header("location: ".$links['status']."?".urlencode("item=incident&action=view&status=-1&place=".$links['home']));
}
?>
This results in sending me the file, but when I open it I receive an error saying:
"File type plain text document (text/plain) is not supported"
First off, I'd start by checking the HTTP headers. You can do this in Firefox easily using the "Live HTTP headers" extension; not sure about equivalents in other browsers offhand. This will let you verify if the header is actually getting set to "application/pdf" and whether your other headers are getting set as well.
If none of the headers are getting set, you might be inadvertently sending output before the calls to header(). Is there any whitespace before the <?php tag?
Are you sure application/pdf is the header your browser is actually seeing?
You can check that out with various HTTP dev tools, for instance HTTP Client for the Mac or Firebug for Firefox.
I use this one and it works.
if(file_exists($file_serverfullpath))
{
header("Pragma: public");
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private", false);
//sending download file
header("Content-Type: application/octet-stream"); //application/octet-stream is more generic it works because in now days browsers are able to detect file anyway
header("Content-Disposition: attachment; filename=\"" . basename($file_serverfullpath) . "\""); //ok
header("Content-Transfer-Encoding: binary");
header("Content-Length: " . filesize($file_serverfullpath)); //ok
readfile($file_serverfullpath);
}
Try prepending "error_reporting(0);". I found this in the comments at http://php.net/readfile (where you took this example from).
Another thing that could be a problem is your file size. There have been issues reported in the past about PHP5 (we're talking 2005 here, so i hope this is fixed by now) having trouble reading files >2MB. If your file size exceeds this you may want to verify that it reads the whole file.