CsvImportForm.php 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297
  1. <?php
  2. /**
  3. * @link:http://www.gdqijianshi.com/
  4. * @copyright: Copyright (c) 2021 广东七件事集团
  5. * 用户操作
  6. * Author: zx
  7. * Date: 2021-03-03
  8. * Time: 13:30
  9. */
  10. namespace common\helpers\csv;
  11. use app\core\ApiCode;
  12. use app\models\BaseModel;
  13. use common\models\base\BaseActiveRecord;
  14. class CsvImportForm extends BaseActiveRecord
  15. {
  16. /**
  17. * 当前模板列数
  18. * @var
  19. */
  20. protected $columnNum = 0;
  21. /**
  22. * 数据读取、组装、验证等配置信息
  23. * @var array
  24. */
  25. protected $importFieldConfig = [];
  26. /**
  27. * 文件信息
  28. * @var
  29. */
  30. protected $file;
  31. /**
  32. * 文件路径
  33. * @var
  34. */
  35. protected $file_path;
  36. /**
  37. * 当前上传文件数
  38. * @var
  39. */
  40. protected $current_num = 1;
  41. /**
  42. * 系统根路径
  43. * @var
  44. */
  45. protected $basePath;
  46. /**
  47. *最终上传的文件路径
  48. * @var
  49. */
  50. protected $path;
  51. /**
  52. * csv配置信息
  53. * @var
  54. */
  55. protected $csvConfig;
  56. /**
  57. * 一次最大可以导入数据量
  58. * @var int
  59. */
  60. protected $maxCount = 0;
  61. /**
  62. * 接收到数据的form表单
  63. * @var
  64. */
  65. protected $dataForm;
  66. /**
  67. * 返回数据类型
  68. * @var
  69. */
  70. protected $returnType = 0;
  71. /**
  72. * @param $returnType
  73. * @return $this
  74. */
  75. public function setReturnType($returnType)
  76. {
  77. $this->returnType = $returnType;
  78. return $this;
  79. }
  80. /**
  81. * @param $maxCount
  82. * @return $this
  83. */
  84. public function setMaxCount($maxCount)
  85. {
  86. $this->maxCount = $maxCount;
  87. return $this;
  88. }
  89. /**
  90. * @param $importFieldConfig
  91. * @return $this
  92. */
  93. public function setImportFieldConfig($importFieldConfig)
  94. {
  95. $this->importFieldConfig = $importFieldConfig;
  96. return $this;
  97. }
  98. /**
  99. * @return array
  100. */
  101. public function getImportFieldConfig()
  102. {
  103. return $this->importFieldConfig;
  104. }
  105. /**
  106. * @param $columnNum
  107. * @return $this
  108. */
  109. public function setColumnNum($columnNum)
  110. {
  111. $this->columnNum = $columnNum;
  112. return $this;
  113. }
  114. /**
  115. * @return mixed
  116. */
  117. public function getColumnNum()
  118. {
  119. return $this->columnNum;
  120. }
  121. /**
  122. * @param $dataForm
  123. * @return mixed
  124. */
  125. public function setDataForm($dataForm)
  126. {
  127. $this->dataForm = $dataForm;
  128. return $this;
  129. }
  130. /**
  131. * @return mixed
  132. */
  133. public function getDataForm()
  134. {
  135. return $this->dataForm;
  136. }
  137. /**
  138. * 获取csv文件数据
  139. * @return array|bool
  140. */
  141. public function readCsvData()
  142. {
  143. $this->basePath = \Yii::$app->basePath;
  144. $this->csvConfig = \Yii::$app->params['csvConfig'];
  145. try {
  146. if (empty($_FILES) || !isset($_FILES['file'])) {
  147. return [
  148. 'code' => 1,
  149. 'msg' => '请上传csv文件'
  150. ];
  151. }
  152. $fileName = $_FILES['file']['name'];
  153. $tmpName = $_FILES['file']['tmp_name'];
  154. $this->path = $this->basePath . '/web/uploads/' . $this->csvConfig['path_folder'] . '/';
  155. if (!is_dir($this->path)) {
  156. mkdir($this->path, 0775, true);
  157. }
  158. $ext = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
  159. if ($ext != 'csv') {
  160. throw new \Exception('请上传csv文件');
  161. }
  162. $uploadFile = $this->path . 'ADMIN-' . date('Y-m-d His') . '.' . $ext;
  163. //上传
  164. move_uploaded_file($tmpName, $uploadFile);
  165. $csvList = $this->readCsv($uploadFile);
  166. if (!empty($this->maxCount) && (count($csvList) > $this->maxCount)) {
  167. throw new \Exception('单次最多导入' . $this->maxCount . '条数据');
  168. }
  169. $data = $csvList;
  170. if ($this->returnType == 1) {
  171. $data = [
  172. 'fileName' => $fileName,
  173. 'tmpName' => $tmpName,
  174. 'csvList' => $csvList,
  175. ];
  176. }
  177. return $data;
  178. } catch (\Exception $exception) {
  179. self::$static_error = $exception->getMessage();
  180. return false;
  181. }
  182. }
  183. /**
  184. * 读取csv文档数据
  185. * @param $file
  186. * @return array
  187. * @throws \Exception
  188. */
  189. public function readCsv($file)
  190. {
  191. try {
  192. setlocale(LC_ALL, array('zh_CN.gbk', 'zh_CN.gb2312', 'zh_CN.gb18030'));
  193. $data = [];//返回的文件数据行
  194. if (!is_file($file) && !file_exists($file)) {
  195. throw new \Exception('csv文件错误');
  196. }
  197. $cvsFile = fopen($file, 'r'); //开始读取csv文件数据
  198. $i = 0;//记录cvs的行
  199. while ($fileData = fgetcsv($cvsFile)) {
  200. $i++;
  201. if ($i == 1) {
  202. $this->verifyTemplate($fileData);
  203. continue;//过滤表头
  204. }
  205. //判断列数是否与模板一致
  206. if (!empty($this->columnNum) && count($fileData) != $this->columnNum) {
  207. throw new \Exception('csv文件数据模板列有误');
  208. }
  209. $arr = [];
  210. if (!empty($fileData)) {
  211. foreach ($this->importFieldConfig as $key => $item) {
  212. $arr[$item['field']] = $this->getNewData($fileData[$key]);
  213. $data[$i] = $arr;
  214. }
  215. }
  216. }
  217. fclose($cvsFile);
  218. return array_values($data);
  219. } catch (\Exception $exception) {
  220. throw $exception;
  221. }
  222. }
  223. /**
  224. * 难测模板头是否一致
  225. * @param $fileData
  226. * @return bool
  227. * @throws \Exception
  228. */
  229. private function verifyTemplate($fileData)
  230. {
  231. try {
  232. foreach ($this->importFieldConfig as $key => $item) {
  233. if (!isset($fileData[$key])) {
  234. throw new \Exception('导入文件的第' . ($key + 1) . '列的标题不存在与模板不一致,正确的标题为:' . $item['field_name']);
  235. }
  236. if (isset($fileData[$key]) && ($item['field_name'] != $this->getNewData($fileData[$key]))) {
  237. throw new \Exception('导入文件的第' . ($key + 1) . '列的标题与模板的不一致,正确的标题为:' . $item['field_name']);
  238. }
  239. }
  240. return true;
  241. } catch (\Exception $exception) {
  242. throw new \Exception($exception->getMessage());
  243. }
  244. }
  245. /**
  246. * @param $data
  247. * @return mixed
  248. */
  249. private function getNewData($data)
  250. {
  251. return mb_convert_encoding(trim($data), "UTF-8", "GBK");
  252. }
  253. }