web-dev-qa-db-ja.com

Laravel=を使用して、テーブルをCSVとしてダウンロードします

Laravelcsvファイルとして使用して、データベーステーブルをエクスポートしようとしています。ユーザーがExport as CSVボタンを選択し、テーブルをcsvファイルとしてダウンロードできるようにしたいと思います。現在、このコードを取得していますが、機能していません:

私のボタン:

<a href="/all-tweets-csv" class="btn btn-primary">Export as CSV</a>

私のルート:

Route::get('/all-tweets-csv', function(){

    $table = Tweet::all();
    $filename = "tweets.csv";
    $handle = fopen($filename, 'w+');
    fputcsv($handle, array('Tweet text', 'screen name', 'name', 'created at'));

    foreach($table as $row) {
        fputcsv($handle, array($row['Tweet_text'], $row['screen_name'], $row['name'], $row['created_at']));
    }

    fclose($handle);

    $headers = array(
        'Content-Type' => 'text/csv',
    );

    return Response::download($handle, 'tweets.csv', $headers);
});

このエラーが返されます:

 The file "Resource id #154" does not exist

そして、私はそれが存在しないファイルをダウンロードしようとしているためだということを集めました。 csvとしてダウンロードするためにコードを変更する代替方法はありますか。

35
Javacadabra

この行を除いて、ほとんどすべてが正常です。

return Response::download($handle, 'tweets.csv', $headers);

この行を次のように変更する必要があります。

return Response::download($filename, 'tweets.csv', $headers);
25

Laravelにデフォルトで何かが組み込まれているかどうかを確認しようとしてここにつまずきました-この質問に対する答えは少し心配です。@andré-danielには、適切な方法は書かないことです最初にファイルを作成しますが、彼の実装は手動で値をまとめています。値に引用符やスペースなどが含まれていると失敗します。

これは、LaravelのResponse::streamおよびphpのfputcsvは、各行を適切にフォーマットします(引用符をエスケープし、必要な文字列を引用します。 http://php.net/manual/en/function.fputcsv.php を参照してください。詳細については)

<?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);
}
62
Erik

編集: この答え を参照して、より良い解決策を見つけてください。以下に回答を残しますが、値をエスケープしない、大きなファイルを生成する場合に不当な量のメモリを使用するなどの問題があることに注意してください。

ディスク上にファイルを不必要に作成しています。ディスクIOを誘発し、2人がそのURLを正確に同時に要求すると問題が発生します(フレームワークの2つのインスタンスが同じファイルに書き込み、破損したサービスを提供するなどの悪いことが起こりますファイルまたは例外でクラッシュする)。

代わりにこれを使用してください:

Route::get('/all-tweets-csv', function() {
    $tweets = Tweets::all();

    // the csv file with the first row
    $output = implode(",", array('Tweet text', 'screen name', 'name', 'created at'));

    foreach ($tweets as $row) {
        // iterate over each Tweet and add it to the csv
        $output .=  implode(",", array($row['Tweet_text'], $row['screen_name'], $row['name'], $row['created_at'])); // append each row
    }

    // headers used to make the file "downloadable", we set them manually
    // since we can't use Laravel's Response::download() function
    $headers = array(
        'Content-Type' => 'text/csv',
        'Content-Disposition' => 'attachment; filename="tweets.csv"',
        );

    // our response, this will be equivalent to your download() but
    // without using a local file
    return Response::make(rtrim($output, "\n"), 200, $headers);
});
16
user2629998

現在の最高ランクの回答 を考慮すると、これはLaravel 5.7 CSV書き込みです。returnの変更に注意してください。

<?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 (new StreamedResponse($callback, 200, $headers))->sendContent();
}
2
Joshua

この行を除くすべてが見栄えが良い:

return Response::download($handle, 'tweets.csv', $headers);

$handleは正しいファイルパスを指していません。以下のように、tweets.csvへのフルパスにする必要があります。

return Response::download($file, 'tweets.csv', $headers);

$file$file = '/path/to/download/tweets.csv'のようなものでなければなりません

1
virtuexru

ここにCSVをダウンロードするための完全なコードがあります

 $headers = array(
        'Content-Type' => 'application/vnd.ms-Excel; charset=utf-8',
        'Cache-Control' => 'must-revalidate, post-check=0, pre-check=0',
        'Content-Disposition' => 'attachment; filename=abc.csv',
        'Expires' => '0',
        'Pragma' => 'public',
    );

$filename = "doenload.csv";
$handle = fopen($filename, 'w');
fputcsv($handle, [
    "id",
    "name"
]);

DB::table("tablename")->chunk(100, function ($data) use ($handle) {
    foreach ($data as $row) {
        // Add a new row with data
        fputcsv($handle, [
            $row->id,
            $row->name
        ]);
    }
});

fclose($handle);

return Response::download($filename, "download.csv", $headers);
1
M Arfan

私はこれらの例をフォローしていましたが、私のコードでは動作しませんでした。私のプロジェクト用に書いたコードを例として添付します。これは、単なる例のガイドのように、OPには対応していません。私のデータはオブジェクトの配列の形式です

public function Export($data) {
    $headers = array(
        "Content-type" => "text/csv",
        "Content-Disposition" => "attachment; filename=summary.csv",
        "Pragma" => "no-cache",
        "Cache-Control" => "must-revalidate, post-check=0, pre-check=0",
        "Expires" => "0"
    );
    $columns = array('Period', 'RevenueArea', 'Subs');

    $callback = function() use ($data, $columns)
    {
        $file = fopen('php://output', 'w');
        fputcsv($file, $columns);

        foreach($data as $items) {
            fputcsv($file, array($items->PERIOD, $items->REVENUE_AREA, $items->SUBS));

        }
        fclose($file);
    };
return Response::stream($callback, 200, $headers)->send();
}

私のreturnステートメントで気付いた場合、csvファイルを生成してダウンロードを初期化する-> send()を含めています。どことして-> sendContent();日付を画面にダンプするだけです。ファイルをダウンロードしていないのと同じ問題でこの投稿に出くわした場合は、公式ドキュメントを確認してください。

https://api.symfony.com/2.3/Symfony/Component/HttpFoundation/StreamedResponse.html

0
jeremiah

これを試して

 $file_name = "abc";
    $postStudent = Input::all();
    $ck = DB::table('loan_tags')->select('LAN')->where('liabilitiesId', $postStudent['id'])->get();
    $i = 0;
    foreach ($ck as $row) { 

                  $apps[$i]['LAN'] = $row->LAN;
                $apps[$i]['Account_number'] =   $postStudent['account_number'];
                $apps[$i]['Bank_Name'] =  $postStudent['bank_name'];
                $i++;
    }

    ob_end_clean();
    ob_start();
    Excel::create($file_name, function($Excel) use($apps){
            $Excel->sheet('Sheetname', function($sheet) use($apps){

               $sheet->row(1, array(
                     'LAN', 'Account number' , 'Bank Name'
                ));
                $k = 2;
                 foreach ($apps as $deta) {
                     $sheet->row($k, array($deta['LAN'],   $deta['Account_number'], $deta['Bank_Name']
                    ));
                    $k++;
                 }
            });
        })->download('xlsx');
0
Tejendra Pareek