FileManager.php 18 KB

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