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.

216 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. /**
  48. * @var function
  49. *
  50. */
  51. public $saveInDatabase;
  52. /**
  53. * @var integer 限制的最大尺寸
  54. */
  55. public $maxSize;
  56. /**
  57. * @var array 允许的文件类型(扩展名)
  58. */
  59. public $allowType;
  60. /**
  61. * @var string 文件保存路径
  62. * template /image/jpg/
  63. */
  64. public $path;
  65. /**
  66. * @var string 数据类型
  67. */
  68. public $dataType;
  69. /**
  70. * @var bool 是否随机文件名(默认为随机,推荐为随机避免中文文件名导致的问题)
  71. */
  72. public $randName = true;
  73. /**
  74. * @var integer 默认单次最大上传数量(1-20
  75. */
  76. public $maxCount;
  77. public function init()
  78. {
  79. if ($this->maxSize === null) {
  80. $this->maxSize = 2048;//默认最大尺寸为2M
  81. }
  82. if ($this->allowType === null) {
  83. $this->allowType = ['*'];//默认允许任何图片类型
  84. }
  85. if ($this->maxCount === null) {
  86. $this->maxCount = 5;//默认单次最大上传数量为5
  87. }
  88. if ($this->dataType === null) {
  89. $this->dataType = self::DATA_TYPE_FORM;//默认上传数据类型为表单数据
  90. }
  91. }
  92. public function run()
  93. {
  94. Yii::$app->response->format = Response::FORMAT_JSON;
  95. $data = [];
  96. try {
  97. if ($this->dataType == self::DATA_TYPE_FORM) {
  98. $file = UploadedFile::getInstanceByName('file');
  99. $this->checkType($file->extension);
  100. $this->checkSize($file->size);
  101. $savePath = $this->getSavePath();
  102. $fileName = $this->getFileName($file->baseName);
  103. $filePath = "$savePath$fileName.{$file->extension}";
  104. $file->saveAs($filePath);
  105. // $data[] = ["uploads/$this->path/$fileName.{$file->extension}"];
  106. } else {
  107. //TODO 非表单类型的文件上传
  108. throw new NotFoundHttpException('未实现');
  109. // $bin = Yii::$app->request->post('file');
  110. // $head = substr($bin, 0, 2);
  111. // $fileExtension = $this->getExtension($head);
  112. // $fileName = $this->getFileName();
  113. // $savePath = $this->getSavePath();
  114. // $filePath = "$savePath/$fileName.{$fileExtension}";
  115. // file_put_contents($filePath, $bin);
  116. }
  117. return ['status' => true, 'path' => "uploads/$this->path$fileName.{$file->extension}", 'alias' => $fileName . '.' . $file->extension];
  118. } catch (\Error $e) {
  119. throw new ServerErrorHttpException($e->getMessage());
  120. // return ['status' => false, 'info' => $e->getMessage()];
  121. }
  122. }
  123. protected function saveData()
  124. {
  125. }
  126. /**
  127. * 检查文件类型是否允许上传
  128. * @param $extension 文件扩展名
  129. * @return bool
  130. * @throws Exception
  131. */
  132. protected function checkType($extension)
  133. {
  134. if (in_array('*', $this->allowType)) {
  135. return true;
  136. }
  137. if (!in_array($extension, $this->allowType)) {
  138. throw new Exception("类型【{$extension}】不被允许,请在配置项中添加该类型");
  139. }
  140. }
  141. /**
  142. * 检查文件尺寸是否超过最大允许上传尺寸
  143. * @param $size 文件尺寸
  144. * @throws Exception
  145. */
  146. protected function checkSize($size)
  147. {
  148. if ($size / 1024 > $this->maxSize) {
  149. throw new Exception("文件大于允许的最大尺寸【{$this->maxSize}】,请修改配置或压缩文件");
  150. }
  151. }
  152. /**
  153. * 根据二进制流头大小判断文件类型
  154. * @param $head
  155. * @return mixed
  156. * @throws NotFoundHttpException
  157. */
  158. protected function getExtension($head)
  159. {
  160. $fileTypes = array(
  161. 7790 => 'exe',
  162. 7784 => 'midi',
  163. 8297 => 'rar',
  164. 255216 => 'jpg',
  165. 7173 => 'gif',
  166. 6677 => 'bmp',
  167. 13780 => 'png'
  168. );
  169. if (isset($fileTypes[$head])) {
  170. return $fileTypes[$head];
  171. } else {
  172. throw new NotFoundHttpException('未找到该文件类型');
  173. }
  174. }
  175. /**
  176. * 获取文件保存路径并创建文件夹
  177. * @return string 文件保存的完成路径
  178. */
  179. protected function getSavePath()
  180. {
  181. $dirs = explode('/', $this->path);
  182. $savePath = Yii::getAlias('@app') . '/web/uploads';
  183. if (!is_dir($savePath)) {
  184. mkdir($savePath, 0755);
  185. }
  186. foreach ($dirs as $dir) {
  187. $savePath .= "/$dir";
  188. if (!is_dir($savePath)) {
  189. mkdir($savePath, 0755);
  190. }
  191. }
  192. return $savePath;
  193. }
  194. /**
  195. * 利用时间戳加随机数构建新文件名
  196. * @param $originName 源文件名
  197. * @return string
  198. */
  199. //TODO 利用原文件名生成新文件名
  200. protected function getFileName($originName = '')
  201. {
  202. return time() . rand(0, 9999);
  203. }
  204. }