UploadController.php 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374
  1. <?php
  2. namespace plugin\admin\app\controller;
  3. use Exception;
  4. use Intervention\Image\ImageManagerStatic as Image;
  5. use plugin\admin\app\controller\Base;
  6. use plugin\admin\app\controller\Crud;
  7. use plugin\admin\app\model\Upload;
  8. use Random\RandomException;
  9. use support\exception\BusinessException;
  10. use support\Request;
  11. use support\Response;
  12. use Throwable;
  13. /**
  14. * 附件管理
  15. */
  16. class UploadController extends Crud
  17. {
  18. /**
  19. * @var Upload
  20. */
  21. protected $model = null;
  22. /**
  23. * 只返回当前管理员数据
  24. * @var string
  25. */
  26. protected $dataLimit = 'personal';
  27. /**
  28. * 构造函数
  29. * @return void
  30. */
  31. public function __construct()
  32. {
  33. $this->model = new Upload;
  34. }
  35. /**
  36. * 浏览
  37. * @return Response
  38. * @throws Throwable
  39. */
  40. public function index(): Response
  41. {
  42. return raw_view('upload/index');
  43. }
  44. /**
  45. * 浏览附件
  46. * @return Response
  47. * @throws Throwable
  48. */
  49. public function attachment(): Response
  50. {
  51. return raw_view('upload/attachment');
  52. }
  53. /**
  54. * 查询附件
  55. * @param Request $request
  56. * @return Response
  57. * @throws BusinessException
  58. */
  59. public function select(Request $request): Response
  60. {
  61. [$where, $format, $limit, $field, $order] = $this->selectInput($request);
  62. if (!empty($where['ext']) && is_string($where['ext'])) {
  63. $where['ext'] = ['in', explode(',', $where['ext'])];
  64. }
  65. if (!empty($where['name']) && is_string($where['name'])) {
  66. $where['name'] = ['like', "%{$where['name']}%"];
  67. }
  68. $query = $this->doSelect($where, $field, $order);
  69. return $this->doFormat($query, $format, $limit);
  70. }
  71. /**
  72. * 更新附件
  73. * @param Request $request
  74. * @return Response
  75. * @throws BusinessException|Throwable
  76. */
  77. public function update(Request $request): Response
  78. {
  79. if ($request->method() === 'GET') {
  80. return raw_view('upload/update');
  81. }
  82. return parent::update($request);
  83. }
  84. /**
  85. * 添加附件
  86. * @param Request $request
  87. * @return Response
  88. * @throws Exception|Throwable
  89. */
  90. public function insert(Request $request): Response
  91. {
  92. if ($request->method() === 'GET') {
  93. return raw_view('upload/insert');
  94. }
  95. $file = current($request->file());
  96. if (!$file || !$file->isValid()) {
  97. return $this->json(1, '未找到文件');
  98. }
  99. $data = $this->base($request, '/upload/files/'.date('Ymd'));
  100. $upload = new Upload;
  101. $upload->admin_id = admin_id();
  102. $upload->name = $data['name'];
  103. [
  104. $upload->url,
  105. $upload->name,
  106. $_,
  107. $upload->file_size,
  108. $upload->mime_type,
  109. $upload->image_width,
  110. $upload->image_height,
  111. $upload->ext
  112. ] = array_values($data);
  113. $upload->category = $request->post('category');
  114. $upload->save();
  115. return $this->json(0, '上传成功', [
  116. 'url' => $data['url'],
  117. 'name' => $data['name'],
  118. 'size' => $data['size'],
  119. ]);
  120. }
  121. /**
  122. * 上传文件
  123. * @param Request $request
  124. * @return Response
  125. * @throws Exception
  126. */
  127. public function file(Request $request): Response
  128. {
  129. $file = current($request->file());
  130. if (!$file || !$file->isValid()) {
  131. return $this->json(1, '未找到文件');
  132. }
  133. $img_exts = [
  134. 'jpg',
  135. 'jpeg',
  136. 'png',
  137. 'gif'
  138. ];
  139. if (in_array($file->getUploadExtension(), $img_exts)) {
  140. return $this->image($request);
  141. }
  142. $data = $this->base($request, '/upload/files/'.date('Ymd'));
  143. return $this->json(0, '上传成功', [
  144. 'url' => $data['url'],
  145. 'name' => $data['name'],
  146. 'size' => $data['size'],
  147. ]);
  148. }
  149. /**
  150. * 上传图片
  151. * @param Request $request
  152. * @return Response
  153. * @throws Exception
  154. */
  155. public function image(Request $request): Response
  156. {
  157. $data = $this->base($request, '/upload/img/'.date('Ymd'));
  158. $realpath = $data['realpath'];
  159. try {
  160. $img = Image::make($realpath);
  161. $max_height = 1170;
  162. $max_width = 1170;
  163. $width = $img->width();
  164. $height = $img->height();
  165. $ratio = 1;
  166. if ($height > $max_height || $width > $max_width) {
  167. $ratio = $width > $height ? $max_width / $width : $max_height / $height;
  168. }
  169. $img->resize($width*$ratio, $height*$ratio)->save($realpath);
  170. } catch (Exception $e) {
  171. unlink($realpath);
  172. return json( [
  173. 'code' => 500,
  174. 'msg' => '处理图片发生错误'
  175. ]);
  176. }
  177. return json( [
  178. 'code' => 0,
  179. 'msg' => '上传成功',
  180. 'data' => [
  181. 'url' => $data['url'],
  182. 'name' => $data['name'],
  183. 'size' => $data['size'],
  184. ]
  185. ]);
  186. }
  187. public function imagetxt(Request $request): Response
  188. {
  189. $data = $this->base($request, '/upload/img/'.date('Ymd'));
  190. $realpath = $data['realpath'];
  191. try {
  192. $img = Image::make($realpath);
  193. $max_height = 1170;
  194. $max_width = 1170;
  195. $width = $img->width();
  196. $height = $img->height();
  197. $ratio = 1;
  198. if ($height > $max_height || $width > $max_width) {
  199. $ratio = $width > $height ? $max_width / $width : $max_height / $height;
  200. }
  201. $img->resize($width*$ratio, $height*$ratio)->save($realpath);
  202. } catch (Exception $e) {
  203. unlink($realpath);
  204. return json( [
  205. 'code' => 500,
  206. 'msg' => '处理图片发生错误'
  207. ]);
  208. }
  209. return json( [
  210. 'code' => 0,
  211. 'msg' => '上传成功',
  212. 'data' => [
  213. 'url' => $data['url'],
  214. 'name' => $data['name'],
  215. 'size' => $data['size'],
  216. ]
  217. ]);
  218. }
  219. /**
  220. * 上传头像
  221. * @param Request $request
  222. * @return Response
  223. * @throws Exception
  224. */
  225. public function avatar(Request $request): Response
  226. {
  227. $file = current($request->file());
  228. if ($file && $file->isValid()) {
  229. $ext = strtolower($file->getUploadExtension());
  230. if (!in_array($ext, ['jpg', 'jpeg', 'gif', 'png'])) {
  231. return json(['code' => 2, 'msg' => '仅支持 jpg jpeg gif png格式']);
  232. }
  233. $image = Image::make($file);
  234. $width = $image->width();
  235. $height = $image->height();
  236. $size = min($width, $height);
  237. $relative_path = 'upload/avatar/' . date('Ym');
  238. $real_path = config('app.public_path', ''). "/$relative_path";
  239. if (!is_dir($real_path)) {
  240. mkdir($real_path, 0777, true);
  241. }
  242. $name = bin2hex(pack('Nn',time(), random_int(1, 65535)));
  243. $ext = $file->getUploadExtension();
  244. $image->crop($size, $size)->resize(300, 300);
  245. $path = config('app.public_path', '') . "/$relative_path/$name.lg.$ext";
  246. $image->save($path);
  247. $image->resize(120, 120);
  248. $path = config('app.public_path', '') . "/$relative_path/$name.md.$ext";
  249. $image->save($path);
  250. $image->resize(60, 60);
  251. $path = config('app.public_path', '') . "/$relative_path/$name.$ext";
  252. $image->save($path);
  253. $image->resize(30, 30);
  254. $path = config('app.public_path', '') . "/$relative_path/$name.sm.$ext";
  255. $image->save($path);
  256. return json([
  257. 'code' => 0,
  258. 'msg' => '上传成功',
  259. 'data' => [
  260. 'url' => "/$relative_path/$name.md.$ext"
  261. ]
  262. ]);
  263. }
  264. return json(['code' => 1, 'msg' => 'file not found']);
  265. }
  266. /**
  267. * 删除附件
  268. * @param Request $request
  269. * @return Response
  270. */
  271. public function delete(Request $request): Response
  272. {
  273. $ids = $this->deleteInput($request);
  274. $primary_key = $this->model->getKeyName();
  275. $files = $this->model->whereIn($primary_key, $ids)->get()->toArray();
  276. $file_list = array_map(function ($item) {
  277. $path =$item['url'];
  278. if (preg_match("#^/app/admin#",$path)){
  279. $admin_public_path = config('app.public_path') ?: base_path() . "/plugin/admin/public";
  280. return $admin_public_path . str_replace("/app/admin", "", $item['url']);
  281. }
  282. return null;
  283. },$files);
  284. $file_list = array_filter($file_list,function ($item){
  285. return !empty($item);
  286. });
  287. $result = parent::delete($request);
  288. if (($res = json_decode($result->rawBody())) && $res->code === 0) {
  289. foreach ($file_list as $file) {
  290. @unlink($file);
  291. }
  292. }
  293. return $result;
  294. }
  295. /**
  296. * 获取上传数据
  297. * @param Request $request
  298. * @param $relative_dir
  299. * @return array
  300. * @throws BusinessException|RandomException
  301. */
  302. protected function base(Request $request, $relative_dir): array
  303. {
  304. $relative_dir = ltrim($relative_dir, '\\/');
  305. $file = current($request->file());
  306. if (!$file || !$file->isValid()) {
  307. throw new BusinessException('未找到上传文件', 400);
  308. }
  309. $admin_public_path = rtrim(config('app.public_path', ''), '\\/');
  310. $base_dir = $admin_public_path ? $admin_public_path . DIRECTORY_SEPARATOR : base_path() . '/plugin/admin/public/';
  311. $full_dir = $base_dir . $relative_dir;
  312. if (!is_dir($full_dir)) {
  313. mkdir($full_dir, 0777, true);
  314. }
  315. $ext = $file->getUploadExtension() ?: null;
  316. $mime_type = $file->getUploadMimeType();
  317. $file_name = $file->getUploadName();
  318. $file_size = $file->getSize();
  319. if (!$ext && $file_name === 'blob') {
  320. [$___image, $ext] = explode('/', $mime_type);
  321. unset($___image);
  322. }
  323. $ext = strtolower($ext);
  324. $ext_forbidden_map = ['php', 'php3', 'php5', 'css', 'js', 'html', 'htm', 'asp', 'jsp'];
  325. if (in_array($ext, $ext_forbidden_map)) {
  326. throw new BusinessException('不支持该格式的文件上传', 400);
  327. }
  328. $relative_path = $relative_dir . '/' . bin2hex(pack('Nn',time(), random_int(1, 65535))) . ".$ext";
  329. $full_path = $base_dir . $relative_path;
  330. $file->move($full_path);
  331. $image_with = $image_height = 0;
  332. if ($img_info = getimagesize($full_path)) {
  333. [$image_with, $image_height] = $img_info;
  334. $mime_type = $img_info['mime'];
  335. }
  336. return [
  337. 'url' => "/$relative_path",
  338. 'name' => $file_name,
  339. 'realpath' => $full_path,
  340. 'size' => $file_size,
  341. 'mime_type' => $mime_type,
  342. 'image_with' => $image_with,
  343. 'image_height' => $image_height,
  344. 'ext' => $ext,
  345. ];
  346. }
  347. }