简体   繁体   English

Laravel 5 控制器中的 CSV 导出

[英]CSV export in laravel 5 controller

So I have made a little ajax request to my reviewsController@export .所以我向我的reviewsController@export提出了一个小小的 ajax 请求。

Now when I console.log() the data in my success method, the ajax response shows the correct data.现在,当我console.log()成功方法中的数据时,ajax 响应显示正确的数据。 However my CSV has not downloaded.但是我的 CSV 还没有下载。 So I have all the right info and have created the csv essentially.所以我拥有所有正确的信息,并且基本上已经创建了 csv。

I think this has possibly to do with setting the headers maybe?我认为这可能与设置标题有关吗?

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();
}

Is there anything I am doing wrong here, or does Laravel have something to cater for this?我在这里做错了什么,或者 Laravel 有什么可以满足这一点的吗?

Try this version out - this should allow you to get a nice output using Response::stream() .试试这个版本 - 这应该允许你使用Response::stream()获得不错的输出。

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);
}

(Adapted from this SO answer: Use Laravel to Download table as CSV ) (改编自这个 SO 答案: Use Laravel to Download table as CSV

Try using a regular link with target="_blank" rather than using JavaScript/AJAX.尝试使用带有target="_blank"的常规链接,而不是使用 JavaScript/AJAX。 Because it's a file download opening in a new tab, the user experience shouldn't be too clunky.因为它是在新选项卡中打开文件下载,所以用户体验不应该太笨拙。

My approach in Laravel 5.7我在 Laravel 5.7 中的方法

/**
 * @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);
}

Try this:尝试这个:

<?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;

}

Note: Works only if you don't load relationships, otherwise it will give exception注意:仅当您不加载关系时才有效,否则会出现异常

This may not answer your question directly, but I'm using a package called ' thephpleague/csv ' for this purpose...这可能无法直接回答您的问题,但我为此使用了一个名为“ thephpleague/csv ”的包...

To use this package:要使用这个包:

  1. composer require league/csv作曲家需要联盟/ csv
  2. Put the following 'use' statements in your controller:将以下“使用”语句放入您的控制器中:

     use Illuminate\\Database\\Eloquent\\Collection; use League\\Csv\\Writer; use Schema; use SplTempFileObject;

    and any model classes you plan on using.以及您计划使用的任何模型类。

  3. Abstract CSV creating code to a function (in your controller), eg:将 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'); }
  4. In your controller, create get function to retrieve/download CSV (replace 'MainMeta' with your own model class):在您的控制器中,创建 get 函数来检索/下载 CSV(用您自己的模型类替换“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'); }

    When you create a route to call this function, it will download a CSV file in your browser, of your chosen Model collection/data.当您创建调用此函数的路由时,它将在您的浏览器中下载您选择的模型集合/数据的 CSV 文件。

  5. Create a route in App\\Http\\routes.php like the following:在 App\\Http\\routes.php 中创建一个路由,如下所示:

     Route::get( '/data/download/main_meta', [ 'as' => 'data/download/main_meta', 'uses' => 'YourController@getMainMetaData' ] );
  6. (Optional) In a blade view file (eg data.blade.php), include a link or button so you can easily access the download url/route: (可选)在刀片视图文件(例如 data.blade.php)中,包含一个链接或按钮,以便您可以轻松访问下载 url/route:

     <p><a href="{{ URL::route('data/download/main_meta') }}" class="btn btn-lg btn-primary pull-left">Download Main Meta Data</a></p>

    When you click on the link, the CSV file will be downloaded in your browser.当您单击该链接时,CSV 文件将下载到您的浏览器中。 In an application I have coded, you will stay on the page you click this link.在我编写的应用程序中,您将停留在单击此链接的页面上。

Of course, this will differ depending on your own application.当然,这将根据您自己的应用程序而有所不同。 There is so much more you can do with this package (full documentation is at http://csv.thephpleague.com/ ).你可以用这个包做更多的事情(完整的文档在http://csv.thephpleague.com/ )。 The project I am using this in is at https://github.com/rattfieldnz/bitcoin-faucet-rotator - I have just started coding on it again after a few months away, so still have a bit of refactoring/testing/tidying up to do :).我正在使用它的项目是在https://github.com/rattfieldnz/bitcoin-faucet-rotator - 几个月后我刚刚开始重新编码,所以仍然有一些重构/测试/整理最多做:)。

I have made a little package LaravelCsvGenerator我做了一个小包LaravelCsvGenerator

and placed it on packagist并将其放在packagist 上

Installation安装

$ composer require  eugene-melbourne/laravel-csv-generator

example of use in your controller在您的控制器中使用的示例

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();
    }

Please, do not hesitate to comment your ideas below this answer.请不要犹豫,在此答案下方评论您的想法。

The simples way最简单的方法

        $headers = [
        'Cache-Control'       => 'must-revalidate, post-check=0, pre-check=0'
        ,   'Content-type'        => 'text/csv'
        ,   'Content-Disposition' => 'attachment; filename=leads.csv'
        ,   'Expires'             => '0'
        ,   'Pragma'              => 'public'
    ];
    $leads = []
    return response(view('exports.leads.csv', [ 'leads' => $leads ]))
        ->withHeaders($headers);

You have to store the file on the server (either temporary or on a disk) and send the url to the file to the frontend.您必须将文件存储在服务器上(临时或磁盘上)并将文件的 url 发送到前端。 Then just trigger a normal download via javascript.然后只需通过javascript触发正常下载。

 public function export(Request $request) { You have to store the file on the server (either temporary or on a disk) and send the url to the file to the frontend. Then just trigger a normal download via javascript. Thank you that's what i just did right now 😄 public function export(Request $request) { $filename = Carbon::now()->format('Ymdhms').'-Products.xlsx'; Excel::store(new ProductsExport, $filename); $fullPath = Storage::disk('local')->path($filename); return response()->json([ 'data' => $fullPath, 'message' => 'Products are successfully exported.' ], 200); } $filename = Carbon::now()->format('Ymdhms').'-Products.xlsx'; Excel::store(new ProductsExport, $filename); $fullPath = Storage::disk('local')->path($filename); return response()->json([ 'data' => $fullPath, 'message' => 'Products are successfully exported.' ], 200); }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM