FileManager.php 20 KB

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