Подтвердить что ты не робот

Использовать Laravel для загрузки таблицы в формате CSV

Я пытаюсь экспортировать таблицу базы данных, используя Laravel в качестве файла csv. Я хотел бы, чтобы пользователь мог выбрать кнопку 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.

4b9b3361

Ответ 1

Почти все отлично, за исключением этой строки:

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

Вы должны изменить эту строку на:

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

Ответ 2

Я споткнулся здесь, пытаясь понять, есть ли у 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);
}

Ответ 3

EDIT: см. этот ответ для лучшего решения; Я сохраню свой ответ ниже, но заметьте, что у него есть такие проблемы, как не ускользание значений и использование необоснованных объемов памяти при генерации больших файлов.

Нет необходимости создавать файл на диске; что вызывает диск IO и вызовет проблемы, если два человека запросят этот URL в одно и то же время (два экземпляра структуры будут записывать в тот же файл, и будут происходить плохие вещи, такие как обслуживание поврежденного файла или сбой с исключением).

Используйте это вместо:

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

Ответ 4

Вот полный код для загрузки 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);

Ответ 5

Все выглядит хорошо, за исключением этой строки:

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

$handle не указывает на правильный путь к файлу. Это должен быть полный путь к tweets.csv, например:

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

где $file должно быть чем-то вроде $file = '/path/to/download/tweets.csv'

Ответ 6

   public function export()
{
    $people = Person::all();

    $csv = \League\Csv\Writer::createFromFileObject(new \SplTempFileObject());

    $csv->insertOne(\Schema::getColumnListing('people'));

    foreach ($people as $person) {
        $csv->insertOne($person->toArray());
    }

    $csv->output('people.csv');
}

Ответ 7

попробуйте это

 $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');