それで、私は_reviewsController@export
_に少しajaxリクエストをしました。
成功メソッドでデータをconsole.log()
すると、ajaxレスポンスに正しいデータが表示されます。ただし、CSVがダウンロードされていません。だから私はすべての正しい情報を持っており、本質的にcsvを作成しました。
これはおそらくヘッダーの設定と関係があると思いますか?
_public function export()
{
header("Content-type: text/csv");
header("Content-Disposition: attachment; filename=file.csv");
header("Pragma: no-cache");
header("Expires: 0");
$reviews = Reviews::getReviewExport($this->hw->healthwatchID)->get();
$columns = array('ReviewID', 'Provider', 'Title', 'Review', 'Location', 'Created', 'Anonymous', 'Escalate', 'Rating', 'Name');
$file = fopen('php://output', 'w');
fputcsv($file, $columns);
foreach($reviews as $review) {
fputcsv($file, array($review->reviewID,$review->provider,$review->title,$review->review,$review->location,$review->review_created,$review->anon,$review->escalate,$review->rating,$review->name));
}
exit();
}
_
ここで私が間違っていることはありますか、Laravelはこれに応えるものがありますか?
このバージョンを試してください-これにより、Response::stream()
を使用してNice出力を取得できます。
public function export()
{
$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"
);
$reviews = Reviews::getReviewExport($this->hw->healthwatchID)->get();
$columns = array('ReviewID', 'Provider', 'Title', 'Review', 'Location', 'Created', 'Anonymous', 'Escalate', 'Rating', 'Name');
$callback = function() use ($reviews, $columns)
{
$file = fopen('php://output', 'w');
fputcsv($file, $columns);
foreach($reviews as $review) {
fputcsv($file, array($review->reviewID, $review->provider, $review->title, $review->review, $review->location, $review->review_created, $review->anon, $review->escalate, $review->rating, $review->name));
}
fclose($file);
};
return Response::stream($callback, 200, $headers);
}
(これから調整SO answer: se Laravel to CSVとしてテーブルをダウンロードする )
JavaScript/AJAXを使用するのではなく、target="_blank"
で通常のリンクを使用してみてください。新しいタブで開くファイルダウンロードであるため、ユーザーエクスペリエンスは不格好ではないはずです。
/**
* @param array $columnNames
* @param array $rows
* @param string $fileName
* @return \Symfony\Component\HttpFoundation\StreamedResponse
*/
public static function getCsv($columnNames, $rows, $fileName = 'file.csv') {
$headers = [
"Content-type" => "text/csv",
"Content-Disposition" => "attachment; filename=" . $fileName,
"Pragma" => "no-cache",
"Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
"Expires" => "0"
];
$callback = function() use ($columnNames, $rows ) {
$file = fopen('php://output', 'w');
fputcsv($file, $columnNames);
foreach ($rows as $row) {
fputcsv($file, $row);
}
fclose($file);
};
return response()->stream($callback, 200, $headers);
}
public function someOtherControllerFunction() {
$rows = [['a','b','c'],[1,2,3]];//replace this with your own array of arrays
$columnNames = ['blah', 'yada', 'hmm'];//replace this with your own array of string column headers
return self::getCsv($columnNames, $rows);
}
これはあなたの質問に直接答えないかもしれませんが、私はこの目的のために「 thephpleague/csv 」と呼ばれるパッケージを使用しています...
このパッケージを使用するには:
次の「use」ステートメントをコントローラーに入れます。
use Illuminate\Database\Eloquent\Collection;
use League\Csv\Writer;
use Schema;
use SplTempFileObject;
および使用する予定のモデルクラス。
(コントローラー内の)関数への抽象CSV作成コード、例:
/**
* A function to generate a CSV for a given model collection.
*
* @param Collection $modelCollection
* @param $tableName
*/
private function createCsv(Collection $modelCollection, $tableName){
$csv = Writer::createFromFileObject(new SplTempFileObject());
// This creates header columns in the CSV file - probably not needed in some cases.
$csv->insertOne(Schema::getColumnListing($tableName));
foreach ($modelCollection as $data){
$csv->insertOne($data->toArray());
}
$csv->output($tableName . '.csv');
}
コントローラーで、CSVを取得/ダウンロードするget関数を作成します(「MainMeta」を独自のモデルクラスに置き換えます)。
public function getMainMetaData(){
$mainMeta = MainMeta::all();
// Note: $mainMeta is a Collection object
//(returning a 'collection' of data from using 'all()' function),
//so can be passed in below.
$this->createCsv($mainMeta, 'main_meta');
}
この関数を呼び出すルートを作成すると、選択したモデルコレクション/データのCSVファイルがブラウザーにダウンロードされます。
次のようにApp\Http\routes.phpにルートを作成します。
Route::get(
'/data/download/main_meta',
[
'as' => 'data/download/main_meta',
'uses' => 'YourController@getMainMetaData'
]
);
(オプション)ブレードビューファイル(data.blade.phpなど)に、リンクまたはボタンを含めて、ダウンロードURL /ルートに簡単にアクセスできるようにします。
<p><a href="{{ URL::route('data/download/main_meta') }}" class="btn btn-lg btn-primary pull-left">Download Main Meta Data</a></p>
リンクをクリックすると、CSVファイルがブラウザにダウンロードされます。私がコーディングしたアプリケーションでは、このリンクをクリックしたページにとどまります。
もちろん、これはアプリケーションによって異なります。このパッケージでできることは他にもたくさんあります(完全なドキュメントは http://csv.thephpleague.com/ にあります)。私がこれを使用しているプロジェクトは https://github.com/rattfieldnz/bitcoin-faucet-rotator にあります-数か月後に再びコーディングを開始しました。リファクタリング/テスト/整理のビット:)。
これを試して:
<?php
public function download()
{
$headers = [
'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0'
, 'Content-type' => 'text/csv'
, 'Content-Disposition' => 'attachment; filename=galleries.csv'
, 'Expires' => '0'
, 'Pragma' => 'public'
];
$list = User::all()->toArray();
# add headers for each column in the CSV download
array_unshift($list, array_keys($list[0]));
$callback = function() use ($list)
{
$FH = fopen('php://output', 'w');
foreach ($list as $row) {
fputcsv($FH, $row);
}
fclose($FH);
};
return Response::stream($callback, 200, $headers); //use Illuminate\Support\Facades\Response;
}
注:リレーションシップを読み込まない場合にのみ機能します。そうしないと例外が発生します
小さなパッケージを作成しました LaravelCsvGenerator
packagist に配置します
Installation
$ composer require eugene-melbourne/laravel-csv-generator
コントローラーでの使用例
class MyController extends Controller
{
public function getCsv(): \Symfony\Component\HttpFoundation\StreamedResponse
{
$data = [
[1, 2.1],
[3, "hi, there"],
];
$headers = ['one', 'two'];
$data = array_merge([$headers], $data);
return (new \LaravelCsvGenerator\LaravelCsvGenerator())
->setData($data)
->renderStream();
}
この回答の下にあなたのアイデアをコメントすることをheしないでください。