CsvExport.php 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211
  1. <?php
  2. namespace common\components;
  3. use yii\base\Component;
  4. class CsvExport extends Component
  5. {
  6. /**
  7. * 导出excel(csv)
  8. * @param array $data
  9. * @param array $headlist
  10. * @param $fileName
  11. */
  12. public function export($data = [], $headlist = [], $fileName)
  13. {
  14. try {
  15. $fileName = urlencode($fileName);
  16. header('Content-Type: application/vnd.ms-excel');
  17. header('Content-Disposition: attachment;filename*=utf-8' . "'zh_cn'" . iconv('utf-8', 'gbk', $fileName) . '.csv');
  18. header('Cache-Control: max-age=0');
  19. //打开PHP文件句柄,php://output 表示直接输出到浏览器
  20. $fp = fopen('php://output', 'a');
  21. //输出Excel列名信息
  22. foreach ($headlist as $key => $value) {
  23. //CSV的Excel支持GBK编码,一定要转换,否则乱码
  24. $headlist[$key] = iconv('utf-8', 'gbk', $value);
  25. }
  26. //将数据通过fputcsv写到文件句柄
  27. fputcsv($fp, $headlist);
  28. //计数器
  29. $num = 0;
  30. //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
  31. $limit = 100000;
  32. //逐行取出数据,不浪费内存
  33. $count = count($data);
  34. for ($i = 0; $i < $count; $i++) {
  35. $num++;
  36. //刷新一下输出buffer,防止由于数据过多造成问题
  37. if ($limit == $num) {
  38. ob_flush();
  39. flush();
  40. $num = 0;
  41. }
  42. $row = $this->handleRowData($data[$i]);
  43. fputcsv($fp, $row);
  44. }
  45. exit();
  46. } catch (\Exception $exception) {
  47. dd($exception->getMessage());
  48. }
  49. }
  50. /**
  51. * 同时导出多个csv文件时,需要弄成压缩包一起下载
  52. * @data 导出数据
  53. * @headlist 第一行,列名
  54. */
  55. public function exportMultiple($data = array(), $headlist = array())
  56. {
  57. try {
  58. $fp = fopen('php://temp/maxmemory:1048576', 'w');
  59. if (false === $fp) {
  60. die('Failed to create temporary file');
  61. }
  62. //输出Excel列名信息
  63. foreach ($headlist as $key => $value) {
  64. //CSV的Excel支持GBK编码,一定要转换,否则乱码
  65. $headlist[$key] = iconv('utf-8', 'gbk', $value);
  66. }
  67. //将数据通过fputcsv写到文件句柄
  68. fputcsv($fp, $headlist);
  69. //计数器
  70. $num = 0;
  71. //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
  72. $limit = 100000;
  73. //逐行取出数据,不浪费内存
  74. $count = count($data);
  75. for ($i = 0; $i < $count; $i++) {
  76. $num++;
  77. //刷新一下输出buffer,防止由于数据过多造成问题
  78. if ($limit == $num) {
  79. ob_flush();
  80. flush();
  81. $num = 0;
  82. }
  83. $row = $this->handleRowData($data[$i]);
  84. fputcsv($fp, $row);
  85. }
  86. rewind($fp);
  87. return $fp;
  88. } catch (\Exception $exception) {
  89. dd($exception);
  90. }
  91. }
  92. /**
  93. * 异步处理超大csv数据
  94. * @data 导出数据
  95. * @headlist 第一行,列名
  96. * @fileName 输出Excel文件名
  97. */
  98. public function ajaxExport($data = array(), $headlist = array(), $fileName)
  99. {
  100. try {
  101. $fileName = $fileName . '.csv';
  102. $newFilePath = \Yii::$app->basePath . \Yii::$app->urlManager->baseUrl . '/temp/goods/';
  103. if (!file_exists($newFilePath . $fileName)) {
  104. if (!is_dir($newFilePath)) {
  105. mkdir($newFilePath, 0777, true);
  106. }
  107. $fp = fopen($newFilePath . $fileName, 'a+');
  108. //输出Excel列名信息
  109. foreach ($headlist as $key => $value) {
  110. //CSV的Excel支持GBK编码,一定要转换,否则乱码
  111. $headlist[$key] = iconv('utf-8', 'gbk', $value);
  112. }
  113. //将数据通过fputcsv写到文件句柄
  114. fputcsv($fp, $headlist);
  115. }
  116. $fp = fopen($newFilePath . $fileName, 'a+');
  117. //计数器
  118. $num = 0;
  119. //每隔$limit行,刷新一下输出buffer,不要太大,也不要太小
  120. $limit = 100000;
  121. //逐行取出数据,不浪费内存
  122. $count = count($data);
  123. for ($i = 0; $i < $count; $i++) {
  124. $num++;
  125. //刷新一下输出buffer,防止由于数据过多造成问题
  126. if ($limit == $num) {
  127. ob_flush();
  128. flush();
  129. $num = 0;
  130. }
  131. $row = $this->handleRowData($data[$i]);
  132. fputcsv($fp, $row);
  133. }
  134. return $fileName;
  135. } catch (\Exception $exception) {
  136. dd($exception->getMessage());
  137. }
  138. }
  139. //判断是否含有英文逗号,英文引号
  140. public function check($value)
  141. {
  142. if (!$this->checkJson($value)) {
  143. $isInt = is_int($value) ? true : false;
  144. $isFloat = is_float($value) ? true : false;
  145. $value = rtrim($value, "\r\n");
  146. $value = str_replace(",", ",", $value);
  147. $value = is_string($value) ? $value . "\t" : $value;
  148. $value = $isInt ? intval($value) : $value;
  149. $value = $isFloat ? floatval($value) : $value;
  150. }
  151. return $value;
  152. }
  153. public function handleRowData($data)
  154. {
  155. $row = $data;
  156. foreach ($row as $key => $value) {
  157. $value = $this->check($value);
  158. $row[$key] = mb_convert_encoding($value, 'GBK', 'UTF-8');
  159. }
  160. return $row;
  161. }
  162. // 判断是否为json数据
  163. private function checkJson($value)
  164. {
  165. $data = json_decode($value);
  166. if ($data && (is_object($data)) || is_array($data)) {
  167. return true;
  168. }
  169. return false;
  170. }
  171. }