laravel-admin的文件管理插件media-manager,迁移到dcat admin中使用
2021-05-13 admin laravel 2960
因Dcat admin中暂无文件管理插件,项目需要在后台管理文件,以前在使用laravel-admin时,比较喜欢media-manager这个插件。这个插件有两种模式,一是表格模式,二是列表模式,如下图:
而且,容易拓展相应的功能,因此,准备将此插件搬到dcat中使用。在迁移过程中,遇到的问题是,需要兼容dcat的前端组件,样式模板需要修改,控制器调用的方法和命名空间也要相应修改。
一、添加路由
在/app/Admin/routes.php中添加以下路由:
$router->get('media', 'MediaController@index')->name('media-index');
$router->get('media/download', 'MediaController@download')->name('media-download');
$router->delete('media/delete', 'MediaController@delete')->name('media-delete');
$router->put('media/move', 'MediaController@move')->name('media-move');
$router->post('media/upload', 'MediaController@upload')->name('media-upload');
$router->post('media/folder', 'MediaController@newFolder')->name('media-new-folder');
二、创建文件管理控制器
在app/Admin/Controllers中创建MediaController.php文件,代码如下:
namespace App\Admin\Controllers;
use App\Admin\Metrics\Examples;
use App\Http\Controllers\Controller;
use Dcat\Admin\Http\Controllers\Dashboard;
use Dcat\Admin\Layout\Column;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Layout\Row;
use Illuminate\Support\Facades\Storage;
use Dcat\Admin\Exception\Handler;
use Illuminate\Http\UploadedFile;
use Illuminate\Http\Request;
use Admin;
class MediaController extends Controller
{
public function index(Request $request,Content $content)
{
$path = $request->get('path', '/');
$view = $request->get('view', 'table');
$manager = new MediaManager($path);
return $content->header('文件管理')->description('点击路径名可快速跳转相应文件夹')->body(view($view,[
'list' => $manager->ls(),
'nav' => $manager->navigation(),
'url' => $manager->urls(),
]));
}
public function download(Request $request)
{
$file = $request->get('file');
$manager = new MediaManager($file);
return $manager->download();
}
public function upload(Request $request)
{
$files = $request->file('files');
$dir = $request->get('dir', '/');
$manager = new MediaManager($dir);
try {
if ($manager->upload($files)) {
admin_toastr(trans('admin.upload_succeeded'));
}
} catch (\Exception $e) {
admin_toastr($e->getMessage(), 'error');
}
return back();
}
public function delete(Request $request)
{
$files = $request->get('files');
$manager = new MediaManager();
try {
if ($manager->delete($files)) {
return response()->json([
'status' => true,
'message' => trans('admin.delete_succeeded'),
]);
}
} catch (\Exception $e) {
return response()->json([
'status' => true,
'message' => $e->getMessage(),
]);
}
}
public function move(Request $request)
{
$path = $request->get('path');
$new = $request->get('new');
$manager = new MediaManager($path);
try {
if ($manager->move($new)) {
return response()->json([
'status' => true,
'message' => trans('admin.move_succeeded'),
]);
}
} catch (\Exception $e) {
return response()->json([
'status' => true,
'message' => $e->getMessage(),
]);
}
}
public function newFolder(Request $request)
{
$dir = $request->get('dir');
$name = $request->get('name');
$manager = new MediaManager($dir);
try {
if ($manager->newFolder($name)) {
return response()->json([
'status' => true,
'message' => trans('admin.move_succeeded'),
]);
}
} catch (\Exception $e) {
return response()->json([
'status' => true,
'message' => $e->getMessage(),
]);
}
}
}
创建文件管理控制器MediaManager.php,代码如下:
namespace App\Admin\Controllers;
use App\Admin\Metrics\Examples;
use App\Http\Controllers\Controller;
use Dcat\Admin\Http\Controllers\Dashboard;
use Dcat\Admin\Layout\Column;
use Dcat\Admin\Layout\Content;
use Dcat\Admin\Layout\Row;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\File;
//use Dcat\Admin\Exception\Handler;
use Illuminate\Http\UploadedFile;
use Illuminate\Http\Request;
use Dcat\Admin\Http\JsonResponse;
use Admin;
class MediaManager extends Controller
{
protected $path = '/';
protected $storage;
protected $fileTypes = [
'image' => 'png|jpg|jpeg|tmp|gif',
'word' => 'doc|docx',
'ppt' => 'ppt|pptx',
'pdf' => 'pdf',
'code' => 'php|js|java|python|ruby|go|c|cpp|sql|m|h|json|html|aspx',
'zip' => 'zip|tar\.gz|rar|rpm',
'txt' => 'txt|pac|log|md',
'audio' => 'mp3|wav|flac|3pg|aa|aac|ape|au|m4a|mpc|ogg',
'video' => 'mkv|rmvb|flv|mp4|avi|wmv|rm|asf|mpeg',
];
public function __construct($path = '/')
{
$this->path = $path;
$this->initStorage();
}
private function initStorage()
{
$disk = config('admin.upload.disk');
$this->storage = Storage::disk($disk);
if (!$this->storage->getDriver()->getAdapter() instanceof Local) {
return JsonResponse::make()->error('只能管理本地文件');
}
}
public function ls()
{
if (!$this->exists()) {
return [];
}
$files = $this->storage->files($this->path);
$directories = $this->storage->directories($this->path);
return $this->formatDirectories($directories)
->merge($this->formatFiles($files))
->sort(function ($item) {
return $item['name'];
})->all();
}
protected function getFullPath($path)
{
return $this->storage->getDriver()->getAdapter()->applyPathPrefix($path);
}
public function download()
{
$fullPath = $this->getFullPath($this->path);
if (File::isFile($fullPath)) {
return response()->download($fullPath);
}
return response('', 404);
}
public function delete($path)
{
$paths = is_array($path) ? $path : func_get_args();
foreach ($paths as $path) {
$fullPath = $this->getFullPath($path);
if (is_file($fullPath)) {
$this->storage->delete($path);
} else {
$this->storage->deleteDirectory($path);
}
}
return true;
}
public function move($new)
{
return $this->storage->move($this->path, $new);
}
/**
* @param UploadedFile[] $files
* @param string $dir
*
* @return mixed
*/
public function upload($files = [])
{
foreach ($files as $file) {
$this->storage->putFileAs($this->path, $file, $file->getClientOriginalName());
}
return true;
}
public function newFolder($name)
{
$path = rtrim($this->path, '/').'/'.trim($name, '/');
return $this->storage->makeDirectory($path);
}
public function exists()
{
$path = $this->getFullPath($this->path);
return file_exists($path);
}
/**
* @return array
*/
public function urls()
{
return [
'path' => $this->path,
'index' => admin_route('media-index'),
'move' => admin_route('media-move'),
'delete' => admin_route('media-delete'),
'upload' => admin_route('media-upload'),
'new-folder' => admin_route('media-new-folder'),
];
}
public function formatFiles($files = [])
{
$files = array_map(function ($file) {
return [
'download' => admin_route('media-download', compact('file')),
'icon' => '',
'name' => $file,
'preview' => $this->getFilePreview($file),
'isDir' => false,
'size' => $this->getFilesize($file),
'link' => admin_route('media-download', compact('file')),
'url' => $this->storage->url($file),
'time' => $this->getFileChangeTime($file),
];
}, $files);
return collect($files);
}
public function formatDirectories($dirs = [])
{
$url = admin_route('media-index', ['path' => '__path__', 'view' => request('view')]);
$preview = "<a href=\"$url\"><span class=\"file-icon text-aqua\"><i class=\"fa fa-folder\"></i></span></a>";
$dirs = array_map(function ($dir) use ($preview) {
return [
'download' => '',
'icon' => '',
'name' => $dir,
'preview' => str_replace('__path__', $dir, $preview),
'isDir' => true,
'size' => '',
'link' => admin_route('media-index', ['path' => '/'.trim($dir, '/'), 'view' => request('view')]),
'url' => $this->storage->url($dir),
'time' => $this->getFileChangeTime($dir),
];
}, $dirs);
return collect($dirs);
}
public function navigation()
{
$folders = explode('/', $this->path);
$folders = array_filter($folders);
$path = '';
$navigation = [];
foreach ($folders as $folder) {
$path = rtrim($path, '/').'/'.$folder;
$navigation[] = [
'name' => $folder,
'url' => admin_route('media-index', ['path' => $path]),
];
}
return $navigation;
}
public function getFilePreview($file)
{
switch ($this->detectFileType($file)) {
case 'image':
if ($this->storage->getDriver()->getConfig()->has('url')) {
$url = $this->storage->url($file);
$preview = "<span class=\"file-icon has-img\"><img src=\"$url\" alt=\"Attachment\"></span>";
} else {
$preview = '<span class="file-icon"><i class="fa fa-file-image-o"></i></span>';
}
break;
case 'pdf':
$preview = '<span class="file-icon"><i class="fa fa-file-pdf-o"></i></span>';
break;
case 'zip':
$preview = '<span class="file-icon"><i class="fa fa-file-zip-o"></i></span>';
break;
case 'word':
$preview = '<span class="file-icon"><i class="fa fa-file-word-o"></i></span>';
break;
case 'ppt':
$preview = '<span class="file-icon"><i class="fa fa-file-powerpoint-o"></i></span>';
break;
case 'xls':
$preview = '<span class="file-icon"><i class="fa fa-file-excel-o"></i></span>';
break;
case 'txt':
$preview = '<span class="file-icon"><i class="fa fa-file-text-o"></i></span>';
break;
case 'code':
$preview = '<span class="file-icon"><i class="fa fa-code"></i></span>';
break;
default:
$preview = '<span class="file-icon"><i class="fa fa-file"></i></span>';
}
return $preview;
}
protected function detectFileType($file)
{
$extension = File::extension($file);
foreach ($this->fileTypes as $type => $regex) {
if (preg_match("/^($regex)$/i", $extension) !== 0) {
return $type;
}
}
return false;
}
public function getFilesize($file)
{
$bytes = filesize($this->getFullPath($file));
$units = ['B', 'KB', 'MB', 'GB', 'TB', 'PB'];
for ($i = 0; $bytes > 1024; $i++) {
$bytes /= 1024;
}
return round($bytes, 2).' '.$units[$i];
}
public function getFileChangeTime($file)
{
$time = filectime($this->getFullPath($file));
return date('Y-m-d H:i:s', $time);
}
}
三、创建模板
在public目录下创建前端js和css资源目录icheck,将下面的附件中的文件包解压到其中。
在resources/views目录中创建两个模板,一个为表格,一个为列表:table.blade.php和list.blade.php,因文件代码较多,就不放在这些。
直接下载链接:http://roujingmei.com:20080/wangpan/JV6,提取码:9379
这样就完成了文件管理功能。