[SOLVED] Had to split the download() method in 2, so it goes as generateCSV() and then getDownload().
After the the generation of the file, added this on sweetalert confirm button, which route points to getDownload().
preConfirm: () => {
window.location.href = "/customers/resale/filterToCSV/download";
}
After the user selects a few checkboxes for filtering a database table, the server writes to a CSV file, but it doesn't prompt the browser to download it.
route:
Route::get('/customers/resale/filterToCSV', 'Resale_customerController#getFilteredQueryResults');
blade view:
axios.get('/customers/resale/filterToCSV', {
params: {
dataFromClient: arrJson,
}
})
.then(function (response) {
Swal.fire({
icon: 'success',
title: '...',
text: '...',
})
console.log("Response (Filtered data to CSV): " + response.data);
});
controller:
public function getFilteredQueryResults(Request $request)
{
$arr = json_decode($request->dataFromClient, true);
$selection = $this->queryBuilderFromCheckboxSelection($arr);
$jsn = $selection->toJson();
$this->download($jsn);
}
which calls the download() method:
public function download($jsn)
{
$filePath = public_path().'\\file.csv';
$headers = array(
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=file.csv",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
);
$jsonDecoded = json_decode($jsn, true);
$csvFileName = 'file.csv';
$fp = fopen($csvFileName, 'w');
foreach ($jsonDecoded as $row) {
fputcsv($fp, $row);
}
fclose($fp);
echo response()->download($filePath, $csvFileName, $headers);
return response()->download($filePath, $csvFileName, $headers);//->deleteFileAfterSend(true);
}
Any idea what am I missing? Thank you!
Related
I am generating a very small CSV-File with only 4 columns and it works fine. When I press the designated button it downloads and I can open it and all the wanted data is present.
However the layout is very weird and it doesn't look good. Here is how it looks:
https://i.stack.imgur.com/klXcw.png
In the upper row are the column names and in the row below is the data.
Here is my code that generates the file:
public function exportData(Bewerbungen $bewerbung) {
$query = Portal::query()->where('email', '=', $bewerbung->bewerber_email)->get();
$headers = [
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=bewerberdaten.csv",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0",
];
$columns = ['id', 'email', 'vorname', 'nachname', 'telefon'];
$callback = function () use ($query, $columns) {
$file = fopen('php://output', 'w');
fputcsv($file, $columns);
foreach ($query as $res) {
fputcsv($file, [$res->id, $res->email, $res->vorname, $res->nachname, $res->telefon]);
}
fclose($file);
};
return Response::stream($callback, 200, $headers);
}
I tried to play around with content encoding, but it is my first time working with csv and file exporting so I have no clue if it is the right direction.
Edit: Better screenshot
https://i.stack.imgur.com/8HvhA.png
The solution was to install this:
https://docs.laravel-excel.com/3.1/getting-started/installation.html
And then changing the variable 'excel_compatibility' => false to true
It is inside the config/excel.php file
This question already has answers here:
How to create and download a csv file from php script?
(8 answers)
Closed 3 years ago.
I am trying to download a query as CSV and face currently two issues:
A file is created in the public folder. It contains the query data. That is really bad, because it should not exist in the public folder.
A file is also downloaded, but the downloaded file is empty.
Here is the function:
public function get_chatmessages(Request $data) {
try {
if ($data->chat_to_user) {
$result = DB::connection('mysql_live')->table('user_chatmessages')
->where(function($query) use($data) {
$query->where('from_user', $data->chat_from_user)->where('to_user', $data->chat_to_user);
})->orWhere(function($query) use($data) {
$query->where('to_user', $data->chat_from_user)->where('from_user', $data->chat_to_user);
})->orderBy('date_added', 'asc')->get();
} else {
$result = DB::connection('mysql_live')->table('user_chatmessages')
->where('from_user', $data->chat_from_user)
->orWhere('to_user', $data->chat_from_user)
->orderBy('date_added', 'asc')
->get();
}
//\Log::info($data);
//\Log::info($result);
$headers = array(
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=file.csv",
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
);
$columns = array('from_user', 'to_user', 'message', 'date_added');
$callback = function() use ($result, $columns) {
$file = fopen('output_chat.csv', 'w');
fputcsv($file, $columns);
foreach($result as $res) {
fputcsv($file, array($res->from_user, $res->to_user, $res->message, $res->date_added));
}
fclose($file);
};
//return response()->download('output_chat.csv', 'DL_output_chat.csv', $headers);
//return response()->make($callback, 200, $headers);
return response()->stream($callback, 200, $headers);
} catch (\Exception $e) {
return redirect('home')->with('error', $e->getMessage());
}
return redirect('home')->with('error', 'Etwas ist schief gelaufen');
}
I made little changes in your snippet regarding php://output
$headers = [
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=output_chat.csv", // <- name of file
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0",
];
$columns = ['from_user', 'to_user', 'message', 'date_added'];
$callback = function () use ($result, $columns) {
$file = fopen('php://output', 'w'); //<-here. name of file is written in headers
fputcsv($file, $columns);
foreach ($result as $res) {
fputcsv($file, [$res->from_user, $res->to_user, $res->message, $res->date_added]);
}
fclose($file);
};
For Laravel, there are many packages which provide us such implementations.
And for you to create download csv file with your database records you can use Laravel Excel package.
This package has many useful features. try to use it.
You can decide where you save files - you can do this using Laravel's Storage facade.
private function pathToPrivateStorage()
{
return '/private/CSVs';
}
Storage::put($this->pathToPrivateStorage, $YOURCSVFILE);
You can read more about storage here.
Try $file = fopen('php://output', 'w'); in place of $file = fopen('output_chat.csv', 'w');
I'm new to react and want to use it with index.php. I made my react project using create-react-app. I researched about it and found that you can use react with php after building it. But I want to work with development mode. Please help me with this.
use another server for PHP;
first debug React, "npm start" http://localhost:3000/
let buttonPHPSet = () => document.getElementById("buttonPHP").addEventListener("click", (e) => {
const that = e.target;
const data = {
"p": "7",
"h": "2",
"P": "3"
};
postAjax("http://my-app.local/controller/HomeController.php", data, (result) => {
let json = JSON.parse(result);
that.textContent = JSON.stringify(json);
console.log(json);
});
}, false);
function postAjax(url, object, success) {
let xhr = new XMLHttpRequest();
xhr.open('POST', url, true); //URL-aдpec интерпретируется относительно страницы, с которой вызывается код, хотя можно указать и абсолютный путь //только готовит его к отправке
xhr.onreadystatechange = () => {
if (xhr.readyState === 4 && xhr.status === 200) {
success(xhr.responseText);
}
};
xhr.setRequestHeader('Content-Type', 'text/plain; charset=UTF-8');
xhr.send(JSON.stringify(object));
// let xhrFormData = new FormData();
// for (const key in object) {
// if (object.hasOwnProperty(key)) {
// xhrFormData.append(key, object[key]);
// }
// }
// xhr.send(xhrFormData);
// const allHeaders = xhr.getAllResponseHeaders();
// xhr.abort();
return xhr;
}
sec debug php whis IIS http://my-app.local/
<?php
header('Access-Control-Allow-Origin: *');
header("Access-Control-Allow-Headers: Content-Type, Access-Control-Allow-Headers, X-Requested-With");
header('Content-Type: text/plain; charset=utf-8');
// header("Access-Control-Allow-Methods: GET, POST, OPTIONS, PUT");
// header('Access-Control-Allow-Credentials: true');
// header('Content-Type: application/json;charset=UTF-8');
// header('Content-type: application/xml');
// header('Content-type: multipart/form-data);
// header('Content-type: text/html;charset=utf-8);
// header('Content-type: application/x-www-form-urlencoded; charset=UTF-8);
$postdata = file_get_contents("php://input");
$postDataDecode = json_decode($postdata);
if($_POST){
$array = [];
foreach ($_POST as $key => $value) {
$array[$key] = $value;
}
echo json_encode($array);
} elseif ($postDataDecode) {
echo json_encode($postDataDecode);
}
?>
vs code
edge
I have a list of users and I want to export it as a CSV file. I binded the button to an Angular controller.
HTML
<a class="btn btn-secondary-icon" href="" ng-click="csv()">Download CSV</a>
JS
$scope.csv = function() {
$scope.export.cols = _.keys(_.pick($scope.data.columns, function(col) {
return parseInt(col.checked) === 1;
}));
$http({
url: $scope.dataUrl,
data: $.param({
export: 1,
csv: $scope.export
}),
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
}
}).success(function(data) {
$rootScope.$broadcast('ErrorOnResponse', data);
if (data.csv) {
Download.download(
'yarooms-report-' + moment().format('YYYY-MM-DD') + '.csv',
'application/csv',
data.csv
);
Analytics.log(Analytics.event.EXPORT, Analytics.category.REPORTING);
}
});
};
My problem occurs when it comes to writing the PHP function that grabs the data from my DB. I even tried to export a simple hardcoded array, but it won't work. When I click the button, it makes a request to the server, but that's all, no downloaded file, nothing.
My testing PHP function:
$file = 'php://memory'
$list = array (
array('aaa', 'bbb', 'ccc', 'dddd'),
array('123', '456', '789'),
array('"aaa"', '"bbb"')
);
$f = fopen($file, 'rw+');
foreach ($list as $fields) {
fputcsv($fp, $fields);
}
rewind($f);
$csv = stream_get_contents($f);
fclose($f);
Support_Model_Entity::logStat('Exported users CSV');
$this->jsonResponse(array(
'csv' => $csv
));
Actually my task is when I select from-date and to-date using date picker and then I click download button, select the id from orders table between dates and check invoice->id is matching with files in storage folder. If files are matched create zip and download.
I can zipped but download is not working.
export.blade.php
<button class="btn btn-success dateDifference" role="button"><i class="fa fa-download"></i> Download </button>
<script>
$(".dateDifference").on("click", function() {
var fromDate = $(".dateFrom").val();
var toDate = $(".dateTo").val();
$.post('{{ route('exportInvoiceDownload') }}', {fromDate: fromDate, toDate: toDate}, function(response){
//alert(response);
});
});
</script>
routes.php
Route::post('/export/download/invoices', [
'as' => 'exportInvoiceDownload', 'uses' => 'BookingController#downloadInvoices'
]);
Controller.php
public function downloadInvoices(Request $request)
{
$fromDateReplace = str_replace('/', '-', $request->fromDate);
$fromDate = date("Y-m-d", strtotime($fromDateReplace));
$toDateReplace = str_replace('/', '-', $request->toDate);
$toDate = date("Y-m-d", strtotime($toDateReplace));
$archive_name = storage_path('app') . '/invoice_archive/Rechnung_'.$fromDate.'_'.$toDate.'.zip';
$orders = Booking::select('invoice_id')
->whereBetween('created_at', [$fromDate, $toDate])
->get();
if (count($orders) > 0 ) {
$zip = new ZipArchive;
if ($zip->open($archive_name, ZipArchive::CREATE) === TRUE) {
foreach ($orders as $order) {
$file = storage_path('app') . '/invoice_archive/test-'.$order->invoice_id.'.pdf';
if (file_exists($file)) {
$zip->addFile($file, 'test-'.$order->invoice_id.'.pdf');
}
}
$zip->close();
$headers = [
'Pragma' => 'public',
'Expires' => 0,
'Content-Type' => 'application/octet-stream',
'Content-Disposition' => 'attachment; filename=\"test_'.$fromDate.'_'.$toDate.'.zip\"',
'Content-Transfer-Encoding' => 'binary'
];
if (file_exists($archive_name)) {
return response()->download($archive_name, 'test_'.$fromDate.'_'.$toDate.'.zip', $headers) /*->deleteFileAfterSend(TRUE)*/;
}
}
}
}
seems you are calling this route with ajax, if that's true than download won't work in this case, you need traditional post request because ajax binary response will not open download popup in browser so instead of ajax just submit the form as browser default or make it get request and open it in new browser tab then it will consider content-dispostion header and download popup will appear.