我正在尝试使用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
。
除了这一行,几乎一切都很好:
return Response::download($handle, 'tweets.csv', $headers);
您应该将此行更改为:
return Response::download($filename, 'tweets.csv', $headers);
我在这里偶然发现,试图看看Laravel是否有默认内置的东西 - 这个问题的答案让我有点担心。我同意@andré-daniel的说法,正确的方法是不先写一个文件,但是他的实现是手动将值组合在一起,如果任何值包含引号,空格等,则会失败。
这是一个更强大的解决方案,使用Laravel的qazxsw poi和php qazxsw poi正确格式化每一行(将转义引号,并引用必要的字符串。有关详细信息,请参阅Response::stream
)
fputcsv
编辑:请参阅http://php.net/manual/en/function.fputcsv.php以获得更好的解决方案;我将在下面保留我的答案,但请注意,如果生成大文件,它会出现诸如无法转义值和使用不合理的内存量等问题。
你不必要地在磁盘上创建一个文件;如果两个人在同一时间请求该URL,则会导致磁盘IO并导致问题(框架的两个实例将写入同一个文件,并且会发生诸如服务损坏的文件或因异常而崩溃)。
请改用:
<?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);
}
考虑到this answer这是Laravel 5.7 CSV写入,请注意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);
});
的变化。
the current highest ranked answer
除了这一行,一切看起来都很好:
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();
}
没有指向正确的文件路径。它应该是tweets.csv的完整路径,例如:
return Response::download($handle, 'tweets.csv', $headers);
其中$handle
应该像return Response::download($file, 'tweets.csv', $headers);
以下是下载CSV的完整代码
$file
我跟着这些例子并没有为我的代码工作。我附上我为项目编写的代码作为示例。这不是解决OP,仅作为示例指南。我的数据是一组对象的形式
$file = '/path/to/download/tweets.csv'
如果你在我的return语句中注意到我包括 - > send(),它会生成csv文件并初始化下载。其中as - > sendContent();只是将日期转储到屏幕上。如果您遇到同样的问题,我发现该文件没有下载,请务必查看官方文档。
$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);
试试这个
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();
}