You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

218 lines
6.5 KiB

  1. <?php
  2. /*
  3. * The MIT License
  4. *
  5. * Copyright 2019 Blobt.
  6. *
  7. * Permission is hereby granted, free of charge, to any person obtaining a copy
  8. * of this software and associated documentation files (the "Software"), to deal
  9. * in the Software without restriction, including without limitation the rights
  10. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  11. * copies of the Software, and to permit persons to whom the Software is
  12. * furnished to do so, subject to the following conditions:
  13. *
  14. * The above copyright notice and this permission notice shall be included in
  15. * all copies or substantial portions of the Software.
  16. *
  17. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  18. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  19. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  20. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  21. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  22. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  23. * THE SOFTWARE.
  24. */
  25. namespace iron\actions;
  26. use yii\base\Action;
  27. use Yii;
  28. use yii\base\Exception;
  29. use yii\web\NotFoundHttpException;
  30. use yii\web\Response;
  31. use yii\web\ServerErrorHttpException;
  32. use yii\web\UploadedFile;
  33. /***
  34. * @author iron <weiriron@gmail.com>
  35. * @created Sep 11, 2019
  36. */
  37. class UploadAction extends Action
  38. {
  39. /**
  40. * 常量:表单数据类型
  41. */
  42. const DATA_TYPE_FORM = 1;
  43. /**
  44. * 常量: 二进制数据类型
  45. */
  46. const DATA_TYPE_BINARY = 2;
  47. public $keyName = 'file';
  48. /**
  49. * @var function
  50. *
  51. */
  52. public $saveInDatabase;
  53. /**
  54. * @var integer 限制的最大尺寸
  55. */
  56. public $maxSize;
  57. /**
  58. * @var array 允许的文件类型(扩展名)
  59. */
  60. public $allowType;
  61. /**
  62. * @var string 文件保存路径
  63. * template /image/jpg/
  64. */
  65. public $path;
  66. /**
  67. * @var string 数据类型
  68. */
  69. public $dataType;
  70. /**
  71. * @var bool 是否随机文件名(默认为随机,推荐为随机避免中文文件名导致的问题)
  72. */
  73. public $randName = true;
  74. /**
  75. * @var integer 默认单次最大上传数量(1-20
  76. */
  77. public $maxCount;
  78. public function init()
  79. {
  80. if ($this->maxSize === null) {
  81. $this->maxSize = 2048;//默认最大尺寸为2M
  82. }
  83. if ($this->allowType === null) {
  84. $this->allowType = ['*'];//默认允许任何图片类型
  85. }
  86. if ($this->maxCount === null) {
  87. $this->maxCount = 5;//默认单次最大上传数量为5
  88. }
  89. if ($this->dataType === null) {
  90. $this->dataType = self::DATA_TYPE_FORM;//默认上传数据类型为表单数据
  91. }
  92. }
  93. public function run()
  94. {
  95. Yii::$app->response->format = Response::FORMAT_JSON;
  96. $data = [];
  97. try {
  98. if ($this->dataType == self::DATA_TYPE_FORM) {
  99. $file = UploadedFile::getInstanceByName($this->keyName);
  100. $this->checkType($file->extension);
  101. $this->checkSize($file->size);
  102. $savePath = $this->getSavePath();
  103. $fileName = $this->getFileName($file->baseName);
  104. $filePath = "$savePath$fileName.{$file->extension}";
  105. $file->saveAs($filePath);
  106. // $data[] = ["uploads/$this->path/$fileName.{$file->extension}"];
  107. } else {
  108. //TODO 非表单类型的文件上传
  109. throw new NotFoundHttpException('未实现');
  110. // $bin = Yii::$app->request->post('file');
  111. // $head = substr($bin, 0, 2);
  112. // $fileExtension = $this->getExtension($head);
  113. // $fileName = $this->getFileName();
  114. // $savePath = $this->getSavePath();
  115. // $filePath = "$savePath/$fileName.{$fileExtension}";
  116. // file_put_contents($filePath, $bin);
  117. }
  118. return ['status' => true, 'path' => "uploads/$this->path$fileName.{$file->extension}", 'alias' => $fileName . '.' . $file->extension];
  119. } catch (\Error $e) {
  120. throw new ServerErrorHttpException($e->getMessage());
  121. // return ['status' => false, 'info' => $e->getMessage()];
  122. }
  123. }
  124. protected function saveData()
  125. {
  126. }
  127. /**
  128. * 检查文件类型是否允许上传
  129. * @param $extension 文件扩展名
  130. * @return bool
  131. * @throws Exception
  132. */
  133. protected function checkType($extension)
  134. {
  135. if (in_array('*', $this->allowType)) {
  136. return true;
  137. }
  138. if (!in_array($extension, $this->allowType)) {
  139. throw new Exception("类型【{$extension}】不被允许,请在配置项中添加该类型");
  140. }
  141. }
  142. /**
  143. * 检查文件尺寸是否超过最大允许上传尺寸
  144. * @param $size 文件尺寸
  145. * @throws Exception
  146. */
  147. protected function checkSize($size)
  148. {
  149. if ($size / 1024 > $this->maxSize) {
  150. throw new Exception("文件大于允许的最大尺寸【{$this->maxSize}】,请修改配置或压缩文件");
  151. }
  152. }
  153. /**
  154. * 根据二进制流头大小判断文件类型
  155. * @param $head
  156. * @return mixed
  157. * @throws NotFoundHttpException
  158. */
  159. protected function getExtension($head)
  160. {
  161. $fileTypes = array(
  162. 7790 => 'exe',
  163. 7784 => 'midi',
  164. 8297 => 'rar',
  165. 255216 => 'jpg',
  166. 7173 => 'gif',
  167. 6677 => 'bmp',
  168. 13780 => 'png'
  169. );
  170. if (isset($fileTypes[$head])) {
  171. return $fileTypes[$head];
  172. } else {
  173. throw new NotFoundHttpException('未找到该文件类型');
  174. }
  175. }
  176. /**
  177. * 获取文件保存路径并创建文件夹
  178. * @return string 文件保存的完成路径
  179. */
  180. protected function getSavePath()
  181. {
  182. $dirs = explode('/', $this->path);
  183. $savePath = Yii::getAlias('@app') . '/web/uploads';
  184. if (!is_dir($savePath)) {
  185. mkdir($savePath, 0755);
  186. }
  187. foreach ($dirs as $dir) {
  188. $savePath .= "/$dir";
  189. if (!is_dir($savePath)) {
  190. mkdir($savePath, 0755);
  191. }
  192. }
  193. return $savePath;
  194. }
  195. /**
  196. * 利用时间戳加随机数构建新文件名
  197. * @param $originName 源文件名
  198. * @return string
  199. */
  200. //TODO 利用原文件名生成新文件名
  201. protected function getFileName($originName = '')
  202. {
  203. return time() . rand(0, 9999);
  204. }
  205. }