FileManager.php 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. <?php
  2. declare(strict_types=1);
  3. /**
  4. * upload文件管理
  5. *
  6. * @version 0.0.0
  7. * @author by huwhois
  8. * @time 2017/11/27
  9. */
  10. namespace app\sys\controller;
  11. use Exception;
  12. use UnexpectedValueException;
  13. use DirectoryIterator;
  14. use think\facade\View;
  15. use think\facade\Config;
  16. use think\File;
  17. use think\Image;
  18. use think\exception\ValidateException;
  19. use think\file\UploadedFile;
  20. use app\common\service\FileService;
  21. use app\common\model\FileManager as FileManagerModel;
  22. use app\common\facade\FileUtils;
  23. class FileManager extends Base
  24. {
  25. protected $modelName = 'FileManager';
  26. protected $t_suffix = '_thumb';
  27. protected $width = 400; // 缩略图高度
  28. protected $height = 300;
  29. protected $storage_path = 'public/storage';
  30. public function index()
  31. {
  32. $param = $this->request->param();
  33. $param['limit'] = isset($param['limit']) ? (int) $param['limit'] : Config::get('app.page_size');
  34. $list = FileManagerModel::queryPage($param);
  35. View::assign('list', $list);
  36. return View::fetch();
  37. }
  38. /**
  39. * 浏览文件
  40. */
  41. public function explorer()
  42. {
  43. $param = $this->request->param();
  44. $activepath = isset($param['activepath']) ? $param['activepath'] : '';
  45. $realpath = $this->app->getRootPath() . $this->storage_path . $activepath;
  46. try {
  47. $dirhandle = new DirectoryIterator($realpath);
  48. $dirs = $files = [];
  49. foreach ($dirhandle as $fileInfo) {
  50. if($fileInfo->isDot() || $fileInfo->getFilename() == '.gitignore') {
  51. continue;
  52. } elseif ($fileInfo->isDir()) {
  53. $dirs[] = $fileInfo->getFilename();
  54. } elseif ($fileInfo->isFile()) {
  55. $files[] = [
  56. 'filename' => $fileInfo->getFilename(),
  57. 'extension' => strtolower($fileInfo->getExtension()),
  58. 'size' => format_bytes($fileInfo->getSize()),
  59. 'time' => $fileInfo->getCTime(),
  60. ];
  61. }
  62. }
  63. $counts = count($dirs) + count($files);
  64. $activeurl = preg_replace("#[\/][^\/]*$#i", "", $activepath);
  65. View::assign([
  66. 'dirs' => $dirs,
  67. 'files' => $files,
  68. 'counts' => $counts,
  69. 'activeurl' => $activeurl,
  70. 'activepath' => $activepath,
  71. ]);
  72. return View::fetch();
  73. } catch(UnexpectedValueException $uve) {
  74. $this->error($uve->getMessage());
  75. }
  76. }
  77. /**
  78. * 附件上传
  79. */
  80. public function uploadFile()
  81. {
  82. $activepath = $this->request->has('activepath') ? $this->request->param('activepath') : '';
  83. $files = $this->request->file('upload_file');
  84. if ($files) {
  85. try {
  86. validate(
  87. [
  88. 'file' => [
  89. // 限制文件大小(单位b),这里限制为10M
  90. 'fileSize' => 10 * 1024 * 1024,
  91. // 限制文件后缀,多个后缀以英文逗号分割
  92. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif,pdf,doc,docx,xls,xlsx,ppt,pptx,txt'
  93. ]
  94. ],
  95. [
  96. 'file.fileSize' => '文件太大',
  97. 'file.fileExt' => '不支持的文件后缀',
  98. ]
  99. )->check(['file' => $files]);
  100. $savenames = [];
  101. $uploadFiles = [];
  102. if (!is_array($files) && $files instanceof UploadedFile) {
  103. $uploadFiles[] = $files;
  104. } else {
  105. $uploadFiles = $files;
  106. }
  107. $url = Config::get('filesystem.disks.public.url');
  108. foreach ($uploadFiles as $file) {
  109. $fileinfo = new FileManagerModel();
  110. $fileinfo->title = $file->getOriginalName();
  111. $fileinfo->filesize = $file->getSize();
  112. $fileinfo->filetime = $file->getCTime();
  113. $fileinfo->fileextension = $file->extension();
  114. $fileinfo->username = $this->getSysUser()->username;
  115. $fileinfo->hash_md5 = $file->md5();
  116. if (empty($activepath)) {
  117. $savename = \think\facade\Filesystem::disk('public')->putFile('/', $file);
  118. $fileinfo->filepath = $url . '/' . $savename;
  119. $fileinfo->filename = basename($savename);
  120. } else {
  121. $savename = $activepath . '/' . $file->hashName();
  122. $savepath = $this->app->getRootPath() . $this->storage_path . $savename;
  123. $file = $file->move($this->app->getRootPath() . $this->storage_path . $activepath, $savepath);
  124. $fileinfo->filepath = $url . $savename;
  125. $fileinfo->filename = $file->hashName();
  126. }
  127. $fileinfo->save();
  128. $savenames[] = $fileinfo->filepath;
  129. }
  130. return json(['code' => 0, 'msg'=>'上传成功', 'filename'=>$savenames]);
  131. } catch (ValidateException $e) {
  132. $this->error($e->getMessage());
  133. }
  134. } else {
  135. $this->error('图片不能为空');
  136. }
  137. }
  138. /**
  139. * 修改文件title
  140. */
  141. public function updateFileTitle($id = 0, $filetitle = '')
  142. {
  143. $fileInfo = FileManagerModel::find($id);
  144. if ($fileInfo == null) {
  145. return json(['code'=>1, 'fileid='.$id.'不存在']);
  146. }
  147. $fileInfo->title = $filetitle;
  148. if ($fileInfo->save()) {
  149. return json(['code'=>0, 'msg'=>'success']);
  150. } else {
  151. return json(['code'=>1, 'msg'=>'failed']);
  152. }
  153. }
  154. /**
  155. * 删除
  156. * @param int|array $id info id
  157. * @return array
  158. */
  159. public function delete($id)
  160. {
  161. if ($this->request->isPost()) {
  162. $whereOp = '=';
  163. if (is_array($id)) {
  164. $whereOp = 'IN';
  165. }
  166. $list = FileManagerModel::where('fileid', $whereOp, $id)->select();
  167. foreach ($list as $value) {
  168. $file = $this->app->getRootPath() . 'public' . $value->filepath;
  169. if (file_exists($file)) {
  170. unlink($file);
  171. }
  172. }
  173. if (FileManagerModel::destroy($id)) {
  174. return ['code' => 0,'msg'=>'删除成功'];
  175. } else {
  176. return ['code' => 1,'msg'=>'删除失败'];
  177. }
  178. }
  179. }
  180. /**
  181. * 删除空目录
  182. */
  183. public function deldir()
  184. {
  185. if ($this->request->isPost()) {
  186. $dir = str_replace('/', DIRECTORY_SEPARATOR, $this->request->param('dir'));
  187. $dir_name = $this->app->getRootPath() . $this->storage_path . DIRECTORY_SEPARATOR . $dir;
  188. try {
  189. rmdir($dir_name);
  190. return ['code' => 0, 'msg' => 'success'];
  191. } catch (Exception $e) {
  192. return ['code' => 1, 'msg' => 'failed, 目录不为空'];
  193. }
  194. }
  195. }
  196. /**
  197. * 删除文件
  198. */
  199. public function delfile()
  200. {
  201. if ($this->request->isPost()) {
  202. $filename = str_replace('/', DIRECTORY_SEPARATOR, $this->request->param('filename'));
  203. $filepath = $this->app->getRootPath() . $this->storage_path . DIRECTORY_SEPARATOR . $filename;
  204. if (unlink($filepath)) {
  205. return ['code' => 0, 'msg' => 'success'];
  206. } else {
  207. return ['code' => 1, 'msg' => 'failed'];
  208. }
  209. }
  210. }
  211. /**
  212. * 图片上传(iframe 页面)
  213. */
  214. public function uploadimg(string $img_id = 'picture', $thumb = false, $width = 400, $height = 300,
  215. $original = false, $id = 0, $cjid = 0)
  216. {
  217. View::assign([
  218. 'img_id' => $img_id,
  219. 'thumb' => $thumb,
  220. 'width' => $width,
  221. 'height' => $height,
  222. 'original' => $original,
  223. 'id' => $id,
  224. 'cjid' => $cjid
  225. ]);
  226. return View::fetch();
  227. }
  228. /**
  229. * 本地图片上传
  230. * @file upload_file 上传的文件
  231. * @param string $img_id 图片ipnut text id 默认值 picture
  232. * @param boolean $thumb 是否制作缩略图
  233. * @param int $width 缩略图最大宽
  234. * @param int $height 缩略图最大高
  235. * @param int $id 信息ID
  236. * @param int $cjid 信息临时ID
  237. * @param bool $saveoriginal 生成缩略图后是否保存原图 默认保存 saveoriginal
  238. */
  239. public function uploadLocalImg(string $img_id = 'picture', $thumb = false, $width = 400, $height = 300,
  240. $original = false, $id = 0, $cjid = 0)
  241. {
  242. if ($this->request->isPost()) {
  243. $file = $this->request->file('upload_file');
  244. if ($file) {
  245. try {
  246. validate(
  247. [
  248. 'file' => [
  249. // 限制文件大小(单位b),这里限制为4M
  250. 'fileSize' => 4 * 1024 * 1024,
  251. // 限制文件后缀,多个后缀以英文逗号分割
  252. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif'
  253. ]
  254. ],
  255. [
  256. 'file.fileSize' => '文件太大',
  257. 'file.fileExt' => '不支持的文件后缀',
  258. ]
  259. )->check(['file' => $file]);
  260. $result = $this->dealUploadImg($file, $thumb, $width, $height, $original, $id, $cjid);
  261. return json([
  262. 'code' => 0,
  263. 'img_id' => $img_id,
  264. 'picname' => $result['picname'],
  265. 'thumb' => $result['thumbname']
  266. ]);
  267. } catch (ValidateException $e) {
  268. $this->error($e->getMessage());
  269. } catch (Exception $e) {
  270. $this->error($e->getMessage());
  271. }
  272. } else {
  273. $this->error('图片不能为空');
  274. }
  275. }
  276. }
  277. /**
  278. * 网络图片上传
  279. * @paran string url_file 网络图片地址
  280. * @param string $img_id 图片ipnut text id 默认值 picture
  281. * @param boolean $water 是否添加水印
  282. * @param boolean $thumb 是否制作缩略图
  283. * @param int $width 缩略图最大宽
  284. * @param int $height 缩略图最大高
  285. * @param bool $overwrite 生成缩略图后是否保存原图
  286. */
  287. public function uploadUrlImg(string $img_id = 'picture', $thumb = false, $width = 400, $height = 300,
  288. $original = false, $id = 0, $cjid = 0)
  289. {
  290. if ($this->request->isPost()) {
  291. $urlImg = $this->request->param('url_file');
  292. if ($urlImg) {
  293. try {
  294. $file = FileUtils::downloadUrlImg($urlImg);
  295. $result = $this->dealUploadImg($file, $thumb, $width, $height, $original, $id, $cjid);
  296. return json([
  297. 'code' => 0,
  298. 'img_id' => $img_id,
  299. 'picname' => $result['picname'],
  300. 'thumb' => $result['thumbname']
  301. ]);
  302. } catch (\think\exception\ValidateException $e) {
  303. $this->error($e->getMessage());
  304. }
  305. } else {
  306. $this->error('图片地址不能为空');
  307. }
  308. }
  309. }
  310. /**
  311. * 选择服务器图片
  312. * @paran string online_file 服务器图片地址
  313. * @param string $img_id 图片ipnut text id 默认值 picture
  314. * @param boolean $water 是否添加水印
  315. * @param boolean $thumb 是否制作缩略图
  316. * @param int $width 缩略图最大宽
  317. * @param int $height 缩略图最大高
  318. * @param bool $overwrite 生成缩略图后是否保存原图
  319. */
  320. public function uploadonlineimg(string $img_id = 'picture', $water = false, $thumb = false, $width = 400, $height = 300, $overwrite = false)
  321. {
  322. if ($this->request->isPost()) {
  323. $pathImg = $this->request->param('online_file');
  324. if ($pathImg && file_exists($this->app->getRootPath() . "public" . $pathImg)) {
  325. $picname = $pathImg;
  326. $thumbname = "";
  327. if ($thumb) {
  328. if (stripos($picname, $this->t_suffix)) {
  329. $thumbname = $pathImg;
  330. } else {
  331. try {
  332. $file = new File($this->app->getRootPath() . "public" . $pathImg);
  333. $ext = $file->getExtension();
  334. $thumbname = str_replace('.' . $ext, '', str_replace('\\', '/', $picname)) . $this->t_suffix . '.' . $ext;
  335. if (!file_exists($thumbname)) {
  336. $image = Image::open($file);
  337. $image->thumb($width, $height, 1);
  338. $image->save($this->app->getRootPath() . "public" . $thumbname);
  339. unset($image);
  340. }
  341. if ($overwrite) {
  342. $picname = $thumbname;
  343. }
  344. } catch (Exception $e) {
  345. $this->error($e->getMessage());
  346. }
  347. }
  348. }
  349. return [
  350. 'code' => 0,
  351. 'img_id' => $img_id,
  352. 'picname' => $picname,
  353. 'thumbname' => $thumbname,
  354. ];
  355. } else {
  356. $this->error('图片地址不存在');
  357. }
  358. }
  359. }
  360. public function onlineimg($page)
  361. {
  362. $files = FileService::getFiles(Config::get('filesystem.disks.public.root'));
  363. if (!count($files)) {
  364. return json_encode(array(
  365. "state" => "no match file",
  366. "list" => array(),
  367. "start" => $page,
  368. "total" => count($files)
  369. ));
  370. }
  371. /* 获取指定范围的列表 */
  372. $page = $page - 1 < 0 ? 0 : (int)$page - 1;
  373. $size = 20;
  374. $start = $page * $size;
  375. $end = $start + $size;
  376. $len = count($files);
  377. for ($i = min($end, $len) - 1, $list = array(); $i < $len && $i >= 0 && $i >= $start; $i--) {
  378. $list[] = $files[$i];
  379. }
  380. return json([
  381. "code" => 0,
  382. "list" => $list,
  383. "page" => $page + 1,
  384. "total" => count($files)
  385. ]);
  386. }
  387. /**
  388. * 判断(远程)文件是否为图片
  389. */
  390. // public function isImg()
  391. // {
  392. // if ($this->request->isAjax()) {
  393. // $filename = $this->request->param('filename');
  394. // $res = \mylib\GetImageByurl::isImg($filename);
  395. // if (!$res) {
  396. // $this->error('该图片不合法');
  397. // } else {
  398. // return ['code'=>2,'msg'=>'图片地址可用'];
  399. // }
  400. // }
  401. // }
  402. /**
  403. * ckeditor 富文本编辑器上传图片
  404. */
  405. public function ckeditorUploadImage()
  406. {
  407. if ($this->request->isPost()) {
  408. $file = $this->request->file('upload');
  409. if ($file) {
  410. try {
  411. validate(
  412. [
  413. 'file' => [
  414. // 限制文件大小(单位b),这里限制为4M
  415. 'fileSize' => 4 * 1024 * 1024,
  416. // 限制文件后缀,多个后缀以英文逗号分割
  417. 'fileExt' => 'jpg,png,gif,jpeg,webp,jfif'
  418. ]
  419. ],
  420. [
  421. 'file.fileSize' => '文件太大',
  422. 'file.fileExt' => '不支持的文件后缀',
  423. ]
  424. )->check(['file' => $file]);
  425. $savename = \think\facade\Filesystem::disk('public')->putFile('/', $file);
  426. return json([
  427. 'uploaded' => 1,
  428. 'fileName' => basename($savename),
  429. 'url' => Config::get('filesystem.disks.public.url') . '/' . $savename
  430. ]);
  431. } catch (\think\exception\ValidateException $e) {
  432. $this->error($e->getMessage());
  433. return json([
  434. 'uploaded' => 1,
  435. 'error' => ['message' => $e->getMessage()]
  436. ]);
  437. }
  438. } else {
  439. return json([
  440. 'uploaded' => 1,
  441. 'error' => ['message' => '图片不能为空']
  442. ]);
  443. }
  444. }
  445. }
  446. /**
  447. * 处理上传的图片
  448. */
  449. protected function dealUploadImg(UploadedFile $file, $thumb, $width, $height, $original, $id, $cjid): array
  450. {
  451. $urlpath = Config::get('filesystem.disks.public.url');
  452. $username = $this->getSysUser()->username;
  453. $savename = str_replace('\\', '/', $file->hashName());
  454. $originalName = $file->getOriginalName();
  455. $thumbname = "";
  456. if ($thumb == true) {
  457. $image = Image::open($file);
  458. $image->thumb($width, $height, 1);
  459. $ext = $file->extension();
  460. if ($original == true) {
  461. \think\facade\Filesystem::disk('public')->putFileAs('/', $file, $savename);
  462. $thumbname = str_replace('.' . $ext, '', $savename) . $this->t_suffix . '.' . $ext;
  463. $savepath = str_replace('\\', '/', Config::get('filesystem.disks.public.root') . '/' . $thumbname);
  464. $image->save($savepath);
  465. FileManagerModel::saveFileInfo($savepath, $thumbname, $originalName, $id, $cjid, $username);
  466. $thumbname = $urlpath . '/' . $thumbname;
  467. } else {
  468. $image->save(Config::get('filesystem.disks.public.root') . '/' . $savename);
  469. }
  470. } else {
  471. \think\facade\Filesystem::disk('public')->putFileAs('/', $file, $savename);
  472. }
  473. $fileinfo = FileManagerModel::saveFileInfo($file, $savename, $originalName, $id, $cjid, $username);
  474. return [
  475. 'picname' => $fileinfo->filepath,
  476. 'thumbname' => $thumbname,
  477. ];
  478. }
  479. }