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');
}
})
})
Related
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));
This question already has answers here:
download file using an ajax request
(13 answers)
Closed 3 years ago.
I'm trying to export a CSV using the Laravel Excel Package https://docs.laravel-excel.com.
I need to pass a few variables in using an ajax request which is all working but the response isn't downloading the CSV.
I'm using the package in a few places without ajax just a simple export and it's all working so I know that side is all good.
Here is the ajax I'm using to send the data:
$(document).ready(function() {
$( "#export" ).on( "click", function() {
let clubInfo = $("#clubInfo select").val();
let funderInfo = $("#funderInfo select").val();
$.ajax({
headers: {'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')},
type: 'post',
url: '{{route('export')}}',
data: {club : clubInfo, funder: funderInfo},
}).done(function(response) {
console.log(response);
}).fail(function() {
console.log("Failed");
});
});
});
Here is the controller that handle the export:
public function adminExport(Request $request)
{
$club = $request->input('club');
$funder = $request->input('funder');
return Excel::download(new UsersExport($club, $funder), 'users.xlsx');
}
I'm not getting any PHP errors or warnings which is all good I'm just getting a response in the network tab which looks like it's the csv it's just not downloading.
The headers of the response are:
Accept-Ranges: none
Cache-Control: public
Connection: keep-alive
Content-Disposition: attachment; filename=users.xlsx
Content-Length: 6812
Content-Type: application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
Unless fetching the file through AJAX is a super hard requirement, I would suggest using window.open('your_url/your_route?club=XXXXX&funder=XXXXX', '_blank'); to download the file and avoiding any headaches.
I think you need to inform the type of export. Note the following:
return (new InvoicesExport)->download('invoices.csv', \Maatwebsite\Excel\Excel::CSV);
But in your controller, I can't see the export type:
return Excel::download(new UsersExport($club, $funder), 'users.xlsx');
If you are using version 2.1, you need to do this:
Excel::create('Filename', function($excel) {
//
})->export('csv');
Or ... what do you think about saving the export first and then exporting it like this?
$file_name = 'my_export';
// Find users first
$users = User::where([['club', $club], ['funder', $funder]])->get();
// then generate the file
Excel::create($file_name, function ($excel) use ($users) {
$excel->sheet('Users', function($sheet) use($users) {
$sheet->fromArray($users);
});
})->store('csv', storage_path('excel/export'));
// Finally, download the file
$full_path = storage_path('excel/export') . '/' . $file_name . '.csv';
return Storage::disk('public')->download($full_path, $file_name . 'csv',
['Content-Description' => 'File Transfer','Content-Type' => 'application/octet-
stream','Content-Disposition' => 'attachment; filename=' . $file_name .
'.csv']);
or maybe you would do that:
$headers = array(
'Content-Type' => 'text/csv',
);
return Response::download($file_name . 'csv', $full_path, $headers);
I would like to ask for your help.
I'm doing a project using CodeIgniter and I need to generate Excel files besides the charts that I'm making. I am using PHPExcel to generate the Excel files.
I added the Classes folder in the third_party folder of the project.
I created a file called Excel.php in the libraries folder of the project with the codes:
<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');
require_once APPPATH."/third_party/Classes/PHPExcel.php";
class Excel extends PHPExcel {
public function __construct() {
parent::__construct();
}
}
In my view file, I used ajax to send the data and process it in the controller which is where I placed the codes for the PHPExcel. Here is my code in the view:
$("#excel").click(function(){
var fromDate = $("#fromDate").val();
var toDate = $("#toDate").val();
var dataString = "fromDate="+fromDate+"&toDate="+toDate;
$.ajax({
//url of the function
url: '<?php echo base_url(); ?>index.php/charts/excel',
//set type post
type: 'POST',
//get the data from the input field
data: dataString,
success:function(data)
{
alert(data);
}
});
});
Here is my code in the controller:
public function excel()
{
$this->load->library('Excel');
//activate worksheet number 1
$this->excel->setActiveSheetIndex(0);
//name the worksheet
$this->excel->getActiveSheet()->setTitle('Users list');
$sDate = $this->input->post('fromDate');//date_create_from_format('Y-m-d', $_POST['fromDate']);
$eDate = $this->input->post('toDate');//date_create_from_format('Y-m-d', $_POST['toDate']);
$data = $this->Charts_model->hello($sDate,$eDate);
// read data to active sheet
//print_r($data);
$row = 1;
foreach($data as $r){
$this->excel->getActiveSheet()->fromArray(array($r->emp_id, $r->emp_stat, $r->isActive, $r->dateStarted), null, 'A'.$row);
$row++;
}
$filename='just_some_random_name.xls'; //save our workbook as this file name
header('Content-Type: application/vnd.ms-excel'); //mime type
header('Content-Disposition: attachment;filename="'.$filename.'"'); //tell browser what's the file name
header('Cache-Control: max-age=0'); //no cache
//save it to Excel5 format (excel 2003 .XLS file), change this to 'Excel2007' (and adjust the filename extension, also the header mime type)
//if you want to save it as .XLSX Excel 2007 format
$objWriter = PHPExcel_IOFactory::createWriter($this->excel, 'Excel5');
//force user to download the Excel file without writing it to server's HD
$objWriter->save('php://output');
}
The controller seems to be working but, it doesnt download any excel file.
So I tried alerting the data returned by the controller and this is how it looks when alerted.
I hope you could help me out with this one. Thanks
UPDATE
The problem is solved. It turns out that it already is downloading the file. As I checked the directory, the file exists.
What I did is I added an anchor tag which is triggered if the export is successful so that it can prompt me that the file is actually downloaded and to be seen below the page.
$("#someid").trigger("click").attr("target", "_blank");
The anchor tag looks like this:
<a href="<?php echo base_url(); ?>/directoryofthefile/somename.xls" style="display: none;">
<input type="button" id="someid" value="Test" class="btn btn-success">
</a>
Extracted from php.net:
If you want the user to be prompted to save the data you are sending, such as a generated PDF file, you can use the ยป Content-Disposition header to supply a recommended filename and force the browser to display the save dialog.
<?php
// We'll be outputting a PDF
header('Content-Type: application/pdf');
// It will be called downloaded.pdf
header('Content-Disposition: attachment; filename="downloaded.pdf"');
// The PDF source is in original.pdf
readfile('original.pdf');
?>
Extrapolating that to your code, I think you're just missing the readfile()
calling. Try to add it once the file has been created.
Good Luck
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.
I have the following PHP code which outputs a document from a web service:
$db->where('documentReference', $post->documentID);
$results = $db->getOne('documents');
$filelocation = 'doc/';
$file = $results['filename'];
header('Content-type: application/vnd.openxmlformats-officedocument.wordprocessingml.document');
header('Content-Length: ' . filesize($filelocation.$file));
header('Content-disposition: attachment; filename="'.$file.'"');
readfile($filelocation.$file);
And on the front end..
APIService.registerUser($scope.formData).then(function(data){
var blob = new Blob([data.data], {type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document'});
var config = {
data: blob,
filename: 'test.docx'
};
FileSaver.saveAs(config);
});
}
When I inspect the data returned from the API the document get returned fine, but when being saved it's always empty?
When calling the API endpoint you need to set the responseType to array buffer like so:
var promise = $http.post('http://someurl', formData, {responseType: 'arraybuffer'});
return promise;
The file then gets saved properly.