I am new to CodeIgniter and was working on downloading a file. However, I want to download a file that resides on my local machine, I am able to locate the file by providing the path, also the file gets downloaded with a File type, However, I want my file to be in .csv format
Here goes my Controller's download function:
public function download()
{
$state_id=$this->input->post('state'); // gets me the state-id from viw's dropdown
$this->load->helper('download'); // Load download helper
$file="C:\\Users\usernew\\Desktop\\New folder\\".$state_id.".csv";
$filename=$state_id.'.csv';
if (file_exists($file))
{
$data = file_get_contents($file); //check file exists
force_download($fileName,$data);
}
else{
echo"not working!";
}
}
Where am I going wrong?
The force_download() takes in two parameters, i.e. the file name and the data to be written to that file. As the file already consists of some sample data, therefore, the function goes like this:
public function download()
{
$state_id=$this->input->post('state'); // gets me the state-id from viw's dropdown
$this->load->helper('download'); // Load download helper
$filename=$state_id.'.csv';
$file="C:\\Users\usernew\\Desktop\\New folder\\".$filename;
if (file_exists($file)) //check file exists
{
force_download($file,NULL); //NULL as the file already has data
}
else{
echo"not working!";
}
}
you can use header function instead force_download:
$file="C:\\Users\usernew\\Desktop\\New folder\\".$state_id.".csv";
$filename=$state_id.'.csv';
header("Content-type: text/csv");
header('Content-Disposition: attachment; filename='.$filename);
readfile( $file );
Related
In Laravel I use this route
Route::get('admin/showBill/{file}','Admin\FileController#showBill');
and this code
class FileController extends AuthController
{
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file) );
if(!\File::exists($path)) return back();
return response()->file($path);
}
to display a pdf from my storage folder.
So if I have the pdf bill-1.pdf in my /storage/app/bills/ folder, then I can view it with the url
example-domain.com/admin/showBill/bill-1.pdf
The problem is that if I open that pdf with the browser, replace it, and refresh (F5) the page, then the old bill is shown. I guess its because its stored in the cache. Can I force Laravel to show the new replaced file?
I tried
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file) );
if(!\File::exists($path)) return back();
$path .= '?v='. time();
return response()->file($path);
}
But then Laravel tells me that this file does not exist. I am looking for a solution where I have not to rename the pdf file.
Are you sure you're replacing the right file?
If so, place this dd(). I've created an endpoint, response an empty pdf file - viewed it - replaced it with a content-filled pdf file and it works just fine when I replace it.
Edit: Also, you should validate the $file variable, using either a formrequest or validating in the controller.
public function showBill($file)
{
$path = storage_path('app/bills/' . basename($file));
if(!\File::exists($path)) {
dd("Quite possibly the problem is here, on the redirect back");
}
return response()->file($path);
}
I want to remove my file from downloads directory after a user has downloaded it. But it is not deleted. I am using Codeigniter download_helper for downloading the file.
Below is my code:
Controller
public function download($key,$id)
{
$link=$this->article->download($key,$id);//get record from database via article model
if(empty($link))
{
show_404();
}
force_download(DOWNLOADS_PATH.$link->file_name, NULL);//download file
$this->article_lib->remove_downloaded($link->file_name);//user has downloaded so now delete this
}
Library
public function remove_downloaded($file_name)
{
if(file_exists(DOWNLOADS_PATH.$file_name))
{
unlink(DOWNLOADS_PATH.$file_name);
}
}
You can find out why it wont be deleted in system/helpers/download_helper.php, there is an exit, so all code you have after force_download() will never be executed.
//File: system/helpers/download_helper.php
// From line 135
// Generate the server headers
header('Content-Type: '.$mime);
header('Content-Disposition: attachment; filename="'.$filename.'"');
header('Expires: 0');
header('Content-Transfer-Encoding: binary');
header('Content-Length: '.$filesize);
header('Cache-Control: private, no-transform, no-store, must-revalidate');
// If we have raw data - just dump it
if ($data !== NULL)
{
exit($data);
}
// Flush 1MB chunks of data
while ( ! feof($fp) && ($data = fread($fp, 1048576)) !== FALSE)
{
echo $data;
}
fclose($fp);
exit;
}
Sorry I was not reading, but the problem with your code is that it is missing the closing )
public function remove_downloaded($file_name)
{
if(file_exists($file_name)) // here is the problem
{
unlink($file_name);
}
}
Also the way the force download works is that anything after will not run. I would suggest using an ajax call after the controller.
UPDATE:
But as you have mentioned in your comment, you can delete the file before creating it as mentioned in this post Unlink after force download not working Codeigniter
I used ignore_user_abort(true) function (docs) to solve this issue, and it worked for me.
Try below code,
public function download($key, $id)
{
$link = $this->article->download($key, $id);//get record from database via article model
if (empty($link)) {
show_404();
}
force_download(DOWNLOADS_PATH . $link->file_name, NULL);//download file
ignore_user_abort(true); // Set whether a client disconnect should abort script execution
if (connection_aborted()) {
$this->article_lib->remove_downloaded($link->file_name);//user has downloaded so now delete this
}
}
While downloading you are passing the full path of the file you want to download but while deleting it, i mean while unlinking it you are passing only filename.
So please do try:
public function download($key,$id)
{
$link=$this->article->download($key,$id);//get record from database via article model
if(empty($link))
{
show_404();
}
force_download(DOWNLOADS_PATH.$link->file_name, NULL);//download file
$this->article_lib->remove_downloaded(DOWNLOADS_PATH.$link->file_name); //Included full path
}
Hope this helps.
just replace in controller function
this:
$this->article_lib->remove_downloaded($link->file_name);
with:
$this->article_lib->remove_downloaded(DOWNLOADS_PATH.$link->file_name);
or maybe with:
$this->article->remove_downloaded(DOWNLOADS_PATH.$link->file_name);
Make sure that you are deleting a file not the directory. if not sure
then try this. it will delete the file and directory also
function rrmdir($dir) {
if (is_dir($dir)) {
$files=scandir($dir);
foreach ($files as $file)
if ($file != "." && $file != "..") rrmdir("$dir/$file");
rmdir($dir);
}
else if (file_exists($dir)) unlink($dir);
}
I have a function that creates an HTML page and forces the download. Once the function is run, for some reason it is downloaded to the users computers twice. Here is my code
public function actionDownload($params)
{
// Get the article
$co_model=new Contentorder;
$co_model->load($params['id']);
$co=$co_model->getFields();
$file_name=str_replace(array(' ','.','&',',','\''),'',strtolower($co['article_title'])).".html";
header('Content-Disposition: attachment; filename="'.$file_name.'"');
header('Content-type: text/html');
echo '<!DOCTYPE html><head><title>'.$co['article_title'].'</title></head><body>';
if ($co['id_contenttype']==3){ // Reusable
$lco_model=new Librarycontent;
$lco_model->load($co['id_librarycontent']);
$res=$lco_model->getFields();
if ($res['id_reusabletype']==3) // Youtube
{
echo $res['reusable_file'];
}
}
echo $co['article'].'</body></html>';
exit;
}
It successfully forces the download on the dynamically created HTML file, but it is downloaded twice for some reason when I only want the file to be downloaded once.
EDIT ------ Here are the headers
I am trying to export a CSV to the browser using Yii and the CSV keeps being filled by Yii log messages.
header('Content-Description: File Transfer');
header('Content-Type: application/csv');
header('Content-disposition: attachment; filename=enrollment_course.csv');
$enrollment = Reports::getEnrollment($courseId);
$separator=",";
foreach ($enrollment as $users)
{
$tmp = array(
$users->userid,
$users->firstname,
$users->lastname,
);
echo join($separator, $tmp)."\n";
}
Yii::app()->end();
Any ideas why this doesn't work properly?
yeah, I actually wrote an extension to do that: http://www.yiiframework.com/extension/csvexport/
Basically it amounts to calling exit, take a look at the last few lines of the example:
// options for file, changing delimeter and enclosure
$content = $csv->toCSV('../myfilename.csv', "\t", "'");
Yii::app()->getRequest()->sendFile($filename, $content, "text/csv", false);
// call exit instead of letting sendFile do it, because if you are using
// CWebLogRoute, the onEndRequest event will fire and output your log and not csv file :(
exit();
I would suggest just killing the script after you've output everything. This prevents anything from being added to the output. A simple 'die' should do the trick.
You can use this code in your controller to disable all logging to the browser for all actions:
protected function beforeAction($action)
{
foreach (Yii::app()->log->routes as $route)
{
if ($route instanceof CWebLogRoute)
{
$route->enabled = false;
}
}
return true;
}
source
I am using dompdf to create a pdf file out of an html file that gets created on-the-fly for the sole purpose of it serving as input for the pdf generator, however I am having trouble doing this, I implemented the code in this thread and everything works fine (I could output a simple pdf) however when I try to give it a more specific url I get this error:
An Error Was Encountered Unable to
load the requested file
here's the code that has the problem:
function printPDF(){
//write_file() usa un helper (file)
$this->load->library('table');
$this->load->plugin('to_pdf');
// page info here, db calls, etc.
$query = $this->db->get('producto');
$data['table'] = $this->table->generate($query);
$path_url = base_url().'print/existencias.html';
write_file($path_url, $data['table']);
$html = $this->load->view($path_url, 'consulta', true);
pdf_create($html, 'consulta');
}
Not sure about the exact problem, but please check this:
1) as stated in CI's manual, load->view's second parameter should be an associative array or an objet, translated to vars via extract. That may generate some problem generating $html.
2) try making $path_url relative to application/views directory, as read in CI's manual.
you should use tcpdf to create a pdf.
//create controller for example :
public function create_pdf()
{
$this->load->library("Pdf");
$data['results'] = // your data
$this->load->view('pdfview',$data);
}
//pdfview is the page having tcpdf code and your pdf code.
You can try it like this
public function export_pdf() {
$filename = 'FILENAME.pdf';
header("Content-Description: Advertise Report");
header("Content-Disposition: attachment; filename=$filename");
header("Content-Type: application/pdf; ");
$file = fopen('php://output', 'w');
$header = array("Question", "Answer", "Name", "Email", "Phone", "Date");
fputpdf($file, $header);
fputpdf($file, 'YOUR DATA');
fclose($file);
exit;
}