问答 / 0 / 3 / 创建于 7年前 / 更新于 7年前
maatwebsite/excel 处理导入excel文件, phpfpm内存飙升, 最新版本: 3.1 文件数据不管多大, php-fpm 都飙升。 有没有解决办法。
用csv吧
@yanthink maatwebsite/excel 这个包的最新版对处理csv有个bug, 检测csv的类型的时候用的是“application/octet-stream” 是使用的php的函数 mime_content_type()获取到的文件类型是 application/octet-stream, 但是在比较的使用的是 text/csv, 这样对比就有问题了。 maatwebsite/excel 直接返回false, 报错找不到文件。
mime_content_type()
application/octet-stream
text/csv
@anziguoer csv 自己写个方法实现更方便
function export_csv($filename, $data, $columns = [], $chunk = 1000000) { if (!$columns) { $firstRow = $data instanceof Generator ? $data->current() : current($data); if (!$firstRow) { exit; } foreach ($firstRow AS $key => $value) { $columns[] = [ 'title' => $key, 'index' => $key, ]; } } header('Content-Type: application/csv; charset=UTF-8'); header('Content-Disposition: attachment; filename="' . $filename . '.csv"'); header('Cache-Control: max-age=0'); $storageDir = rtrim(sys_get_temp_dir(), '/'); $prefix = str_random(10); $fileList = []; // 文件集合 $fileList[] = $file = "$storageDir/${prefix}_${filename}_1.csv"; $fp = fopen($file, 'w'); fputs($fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); $head = array_pluck($columns, 'title'); fputcsv($fp, $head); // 计数器 $i = 0; // 每隔$limit行刷新一下输出buffer,不要太大,也不要太小 $limit = 10000; // 行上限 $maxLimit = 100000000; foreach ($data as $item) { if ($i >= $maxLimit) { break; } if ($i > 0 && $i % $chunk == 0) { fclose($fp); // 关闭上一个文件 $j = $i / $chunk + 1; $fileList[] = $file = "$storageDir/${prefix}_${filename}_$j.csv"; $fp = fopen($file, 'w'); fputs($fp, chr(0xEF) . chr(0xBB) . chr(0xBF)); fputcsv($fp, $head); } $i++; if ($i % $limit == 0) { ob_flush(); flush(); } $row = []; foreach ($columns AS $column) { $value = isset($column['index']) ? (is_object($item) ? $item->{$column['index']} : $item[$column['index']]) : null; $render = array_get($column, 'render'); if ($render && $render instanceof Closure) { $row[] = $render($value, $item); } else { if (is_numeric($value) && strlen($value) > 10) { $value .= "\t"; } $row[] = $value; } } fputcsv($fp, $row); unset($row); } fclose($fp); if (count($fileList) > 1) { $zip = new ZipArchive(); $oldFilename = $filename; $filename = "$storageDir/${prefix}_${filename}.zip"; $zip->open($filename, ZipArchive::CREATE); // 打开压缩包 foreach ($fileList as $file) { $zip->addFile($file, str_replace("${prefix}_", '', basename($file))); // 向压缩包中添加文件 } $zip->close(); // 关闭压缩包 foreach ($fileList as $file) { @unlink($file); // 删除csv临时文件 } // 输出压缩文件提供下载 header("Cache-Control: max-age=0"); header("Content-Description: File Transfer"); header('Content-disposition: attachment; filename=' . $oldFilename . '.zip'); header("Content-Type: application/zip"); // zip格式的 header("Content-Transfer-Encoding: binary"); header('Content-Length: ' . filesize($filename)); } else { $filename = head($fileList); } @readfile($filename); @unlink($filename); // 删除临时文件 exit; } $sql = "SELECT * FROM users"; $users = DB::cursor($sql); $columns = [ [ 'title' => '用户ID', 'index' => 'id', ], [ 'title' => '用户名称', 'index' => 'name', ], [ 'title' => '电子邮箱', 'index' => 'email', ], [ 'title' => '注册日期', 'index' => 'created_at', 'render' => function ($createdAt, $item) { return substr($createdAt, 0, 10); } ], ]; export_csv('用户列表', $users, $columns);
我要举报该,理由是:
用csv吧
@yanthink maatwebsite/excel 这个包的最新版对处理csv有个bug, 检测csv的类型的时候用的是“application/octet-stream” 是使用的php的函数
mime_content_type()获取到的文件类型是application/octet-stream, 但是在比较的使用的是text/csv, 这样对比就有问题了。 maatwebsite/excel 直接返回false, 报错找不到文件。@anziguoer csv 自己写个方法实现更方便