How to download the xls file using codeigniter - php

Here i have one button, if i click the button means i want to download the one demo.xls file,using php i did, but now i want to do codeigniter, i tried but i am not able to do? please see my below code
<button class="btn btn-warning" id="download-btn">
<i class="fa fa-download" aria-hidden="true"></i> Download Demo File
</button>
<script type="text/javascript">
$(document).ready(function(){
$("#download-btn").click(function(e){
e.preventDefault();
$.ajax({
type:'POST',
url :"Staff/downloadDemoFile",
cache: false,
contentType: false,
processData: false,
success: function(data) {
console.log(data);
},
error:function(exception){
alert('Exeption:'+exception);
}
});
});
});
</script>
My controller
public function downloadDemoFile()
{
if($this->session->logged_in != TRUE){
$this->load->view('login');
}
else{
$download= $this->Add_staff_model->downloadFile();
}
}
My model
public function downloadFile()
{
$sFileName = 'demo.xls';
header("Cache-Control: public");
header("Content-Description: File Transfer");
header("Content-Disposition: attachment; filename=$sFileName");
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: binary");
// read the file from disk
readfile(UPLOAD_PATH_XLS.$sFileName);
}

Downloading a file from disk is pretty straightfoward using CodeIgniter Download Helper. Read the manual here.
public function downloadFile()
{
// load the helper somewhere, i.e in the constructor.
$this->load->helper('download');
// Use it when necessary
$sFileName = 'demo.xls'; // filename to be download. With path if necessary: /path/to/demo-xls
force_download($sFileName, NULL);
}
As a final consideration, in such a situation I wouldn't put the downloadFile() method in the model but in the controller itself.

Related

JPG (Binary data) download as AJAX response

I have a page where a user can download an image in the format he ask, the request is sent to a PHP script that produce the image and ... I want to serve to the user.
This is the JQUERY code sourced here on StackOverflow
$('[name ="download_img_ajax"]').click(function(e){
e.preventDefault()
var element = this
var formdata = new FormData(element.closest(".form_downIMG"))
formdata.append('download_img_ajax','true')
$(this).next("span.down_response").html('Preparazione file in corso...'),
$('.emailadr').hide(),
$.ajax({
type: 'POST',
url: '$target_post',
data: formdata,
cache: false,
contentType: false,
processData: false,
success: function(tornato) {
const blob = new Blob([tornato], {type: 'image/jpeg'});
const downloadUrl = URL.createObjectURL(blob);
const a = document.createElement("a");
a.href = downloadUrl;
a.download = "file.jpg";
document.body.appendChild(a);
a.click();
},
})
})
The PHP script generate the file as a tmp file ($img), but I don't understand how return it as a correct AJAX response.
echo fread($img,filesize($img_path));
isn't working (the file isn't recognized as JPG file) even if the size is correct.
In a normal form I return the file this way:
header('Content-Transfer-Encoding: binary'); // For Gecko browsers mainly
header('Accept-Ranges: bytes'); // For download resume
header('Content-Length: ' . filesize($img_path)); // File size
header('Content-Encoding: none');
header('Content-Type: image/jpeg'); // Change this mime type if the file is not PDF
header('Content-Disposition: attachment; filename=' . $imgID); // Make the browser display the Save As dialog
readfile($img_path);
fclose($img);
PS: In JQ I use next, closest, etc. because I have many forms in the same dynamically generated by PHP.
I will use this kind of download only for file of ~700KB, leaving the bigger file on the old method of a submit form with target="_blank" and readfile in the PHP. Is safe?
If I want manage also error (example the PHP script can't serve the file) how I can handle it?
Thanks.
Solved with FileSaver.js ( https://github.com/eligrey/FileSaver.js )
var xhr = new XMLHttpRequest()
xhr.open('POST', '$target_post')
xhr.responseType = 'blob'
xhr.onload = function() {
saveAs(xhr.response, 'immagine.jpg');
}
xhr.send(formdata)
the PHP
echo fread($img,filesize($img_path));

Return images via PHP and set as src with AJAX

I have some problems when I try to display multiple images (well it doesn't work for one image so multiple is impossible), and what I'm doing is with my function of AJAX to recover from my db, all the images location string that are in the table images. Then it calls another function called setImages() which receives those strings of the image locations and I use iterate over the strings (using jQuery's .each()) to trigger an AJAX request that calls a php script named image.php?img=[data]. data is the string containing the image location, so I have something like the code below:
The problem is that setImages() of my js, doesn't show the images
the PHP file:
<?php
$init="/var/Imagenes/cursos/";
$img=$_GET['img'];
$path=$init.$img;
echo $path;
//el path debe ser autores/ or cursos/
$name="azure";
/*
header("Cache-Control: no-cache, must-revalidate");
header("X-Sendfile: $path");
header("Content-Type: image/jpeg");
header("Content-Disposition: inline; filename='archivos'");
*/
//el nombre de la base de datos de la imagen
header("Cache-Control: no-cache, must-revalidate");
if((isset($path)&& !is_null($path))){
header("X-Sendfile: $path");
if(strpos( $img, ".png" )||strpos( $img, ".PNG" )){
header("Content-Type: image/PNG;base64");
}
elseif(strpos( $img, ".jpg" )||strpos( $img, ".JPG" )){
header("Content-Type: image/jpg;base64");
}
elseif(strpos( $img, ".jpeg" )||strpos( $img, ".JPEG" )){
header("Content-Type: image/jpeg;base64");
}
else{
return "error.jpg";
}
$newimg=rand(1000 , 9999 );
header("Content-Disposition: inline; fileimg= $newimg-$img");
exit();
}
else{
echo "no se pudo realizar la consulta";}
JS code:
functions listImgCursos works fine...
function listImgCursos(identificador) {
var resultado= $.ajax({
url: consultaBasica,
cache: false,
type: 'POST',
data : { action: "imgCursos"}
}).then(
function(data){// Success
var flagErrFound = false;
var nf404 = "" ;
$.each(data,
function(index,datos){
if((datos['id']===null)||(datos['img']=="")||(datos['img']==null)){
nf404 = datos['id'];
flagErrFound= true;
}//if close
}//function close
)//each close
if(flagErrFound===true){
error = {error: "CX02", msj: "Failed to get data from records.", data: nf404 };
return $.Deferred().reject(error);
}
else
return data;
},//function sucessful
function(){// fail
error = {error: "CX01", msj: "Failed to execute ajax"};
return $.Deferred().reject(error);
}//function fail
);//then;
resultado.done(
function (data){//success
setImages(data);
}//function DONE
);
resultado.fail(
function(e){//function fail
console.log(e.msj + " "+ e.error + ":" + e.data );
}//function FAIL)
);
}
function setImages(data){
$.each(data, function (index, datos) {
var temp="../classes/imagen.php?img="+encodeURIComponent(datos['img'])+"&t="+((new Date).getTime());
console.log(temp); // returns something like: ../classes/imagen.php?img=curso-2561.jpg&t=1489074434134
$.ajax({
url: temp,
type: "GET",
dataType: "image/jpg;base64",
async:true,
cache: false,
success: function(datai){
console.log(datai);
$('#pickimg').append('<img src="data:image/png;base64,' + datai + '" />');
},
fail: function(){
}
});
});
The problem is that setImages() of my js, doesn't show the images
This is because of multiple reasons:
The PHP code isn't actually returning the file contents. To do that, use a function like file_get_contents(),
readfile(), etc. Also, the string should be base-64 encoded so use base64_encode().
$newimg=rand(1000 , 9999 );
header("Content-Disposition: inline; fileimg= $newimg-$img");
echo base64_encode(file_get_contents($path));
exit();
This may be redundant with the first bullet, but the Syntax for header Content-Disposition only contains three directives: name, filename and filename*.1. So that fileimg directive is invalid. That header could include the filename directive but because a string is being returned it would be useless:
header("Content-Disposition: inline; filename=\"$newimg-$img\"");
In that sense it isn't really returning an image, so the headers for Content-Type are basically incorrect. Consequently, the AJAX call (using $.ajax()) should not specify the dataType (i.e. dataType: "image/jpg;base64" which wouldn't be dynamic anyway - for jpgs, pngs, etc). So remove that dataType option.
See a demonstratation of this with the modifications applied in this phpFiddle. Click the button labeled Run - F9 - and then when the frame loads, click the button labeled Update to trigger an AJAX call to the PHP script which will load a PNG image and append it to the element with id attribute "pickimg".
1https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Disposition#Directives

Can't direct download after creating a CSV file

I've seen a lot of answers of this type of questions but none worked for me. I've a CSV object which has a createCSV function like this :
public function createCSV($url, $delimiter = ","){
$file = fopen($url, 'w');
foreach ($this->content as $line) {
fputcsv($file, $line, $delimiter);
}
fclose($file);
}
And I want to download it directly from the browser so here is what I do :
header('Content-type: text/csv');
header('Content-Disposition: attachment; filename="'.$filename.'"');
$csv_file->createCSV('php://output');
This part of code is execute with an AJAX call and even if the header is set to text/csv the download doesn't work but in the response tab I can see the content of my csv. I've tried with different header but none of them worked. How can I do to download the CSV ?
EDIT
The thing is that I don't have a URL for my CSV and I don't want to store the file somewhere, I just want to build the file and download directly with the browser
Try this code:
$('#exportcsv').click(function(){
var self = this;
$.ajax({
url : '/exportcsv',
method : 'get',
success : function(response)
{
console.log(response);
var csvData = 'data:application/csv;charset=UTF-8,' + encodeURIComponent(response);
$(self).attr({
'download': 'publisher.csv',
'href': csvData,
'target': '_blank'
});
// window.open(uri, 'test.csv');
}
})
})

force_download in ajax and php

How can I download using force_download php in ajax,
Is it possible ???
I have an ajax request like this :
function save(path, namaFile, namaExcel) {
$.ajax({
url: "<?php echo site_url('members/program_kecil/program_kecil/convert_csv_ke_excel'); ?>",
type: 'post',
data: {path: path,
nama: namaFile,
namaExcel: namaExcel
},
success: function (response) {
$('#modal_form').modal('hide'); // show bootstrap modal
}
});
}
This is the php :
class Program_kecil extends Members_Controller{
public function convert_csv_ke_excel() {
require_once APPPATH . "/libraries/CSVToExcelConverter.php";
$this->load->helper('file');
$this->load->helper('download');
CSVToExcelConverter::convert($this->input->post('path'), $this->input->post('namaExcel'));
$this->download_excel($this->input->post('namaExcel'));
echo json_encode($this->input->post('namaExcel'));
}
public function download_excel($file) {
header('Content-type: application/ms-excel');
header('Content-Disposition: attachment; filename=' . $file);
$filedownload = file_get_contents($file);
force_download($filedownload, null);
}
I just got my modal is closed;
P.S : in success ajax (callback) like this:
"D:\/xampp\/htdocs\/develop_tsurumaru\/assets\/uploads\/LJTD2508.xlsx"
Which is the path of excel will be downloaded.
Please advise.
Through AJAX you can't download file directly, You will need to open that path in new tab to download it.
Like this,
window.open('http://YOUR_HOST/develop_tsurumaru/assets/uploads/LJTD2508.xlsx', '_blank');
Update the URL to access the file from web instead of file system.

Downloading an Excel File with php

I am trying to download an excel file to the client that I save on the server first (for backup purposes). The problem is I get a completely different file server side than I do client side. The server side is correct, the client side lists my sql queries and the time it takes. Note the xlsx is multiple sheets in one workbook and it needs to be that way.
public static function generate()
{
//Override the max execution time because our report takes longer than 30 seconds to run
ini_set("max_execution_time", 300);
$objPHPExcel = new PHPExcel();
$objPHPExcel = ErsReport::generateDemographics($objPHPExcel);
$objPHPExcel = ErsReport::generateWorkLocationTab($objPHPExcel);
$objPHPExcel = ErsReport::generateDisabilityCategoryTab($objPHPExcel);
$objWriter = PHPExcel_IOFactory::createWriter($objPHPExcel, 'Excel2007');
$objWriter->save('ERS Reports\SpeedERS_'.date("Y_m_d").'.xlsx');
//$objWriter->save('SpeedERS.xlsx');
}
public static function download()
{
header ('Content-Type: application/vnd.ms-excel; charset=utf-8');
header ('Content-Disposition: attachment; filename="ERS Reports\SpeedERS_'.date("Y_m_d").'.xlsx"');
header("Expires: 0");
header("Cache-Control: must-revalidate, post-check=0, pre-check=0");
header("Cache-Control: private",false);
readfile('ERS Reports\SpeedERS_'.date("Y_m_d").'.xlsx');
}
I call generate then download. The generate shows the correct data.
When I call download it shows improper data and only one page.
EDIT
The function calling generate & download.
function submitERSReport (formLocation) {
{{ErsReport::generate();}}
{{ErsReport::download();}}
}
I called it like this instead.
function submitERSReport () {
$.ajax({
url: "/report/generateERS",
type: "POST",
dataType: "json",
error: function(XMLHttpRequest, textStatus, errorThrown){
alert("Request failed: getting ERS: " + textStatus + " " + errorThrown);
},
success: function(msg){
var iframe = document.createElement("iframe");
iframe.style.display = "none";
iframe.src = msg.filename;
$('body').append(iframe);
}
});
}
With this controller.
public function action_generateERS()
{
$filename = ErsReport::generate();
return json_encode(array("filename"=>$filename));
}
And I made one change to the model.
$objWriter->save($_SERVER['DOCUMENT_ROOT'].'/ERS/SpeedERS_'.date("Y_m_d").'.xlsx');
return('/ERS/SpeedERS_'.date("Y_m_d").'.xlsx');
It works now, but I'm still open to suggestions.

Categories