tp/app/admin/controller/System/FileController.php

598 lines
20 KiB
PHP

<?php
namespace app\admin\controller\System;
use app\admin\BaseController;
use think\facade\Filesystem;
use think\facade\Request;
use think\facade\Db;
use think\Response;
use app\model\System\FilesCategory;
use app\model\System\Files;
class FileController extends BaseController
{
// 文件类型映射
protected $fileTypes = [
'image' => 1,
'document' => 2,
'video' => 3,
'audio' => 4
];
// 允许的文件类型
protected $allowedExtensions = [
'image' => ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'],
'document' => ['pdf', 'doc', 'docx', 'xls', 'xlsx', 'ppt', 'pptx', 'txt'],
'video' => ['mp4', 'webm', 'mov'],
'audio' => ['mp3', 'wav', 'ogg']
];
// 获取所有文件
public function getAllFiles()
{
try {
$page = Request::param('page/d', 1);
$pageSize = Request::param('pageSize/d', 10);
$cate = Request::param('cate/d', 0);
$keyword = Request::param('keyword/s', '');
$query = Files::where('delete_time', null)
->where('tid', $this->getTenantId());
if ($cate) {
$query->where('cate', $cate);
}
if ($keyword) {
$query->whereLike('name', "%{$keyword}%");
}
$total = $query->count();
$list = $query->page($page, $pageSize)
->order('create_time', 'desc')
->select();
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'pageSize' => $pageSize
]
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取文件列表失败: ' . $e->getMessage()
]);
}
}
//获取用户分类
public function getUserCate()
{
try {
$tid = $this->getTenantId();
// 只根据 tid 筛选分类
$cate = FilesCategory::where('delete_time', null)
->where('tid', $tid)
->field('id,name')
->select();
// 获取每个分类下的文件数量
foreach ($cate as &$c) {
$c['total'] = Files::where('cate', $c['id'])
->where('tid', $tid)
->where('delete_time', null)
->count();
}
return json([
'code' => 200,
'msg' => 'success',
'data' => $cate
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取用户分类失败: ' . $e->getMessage()
]);
}
}
//新建文件分组
public function createFileCate()
{
try {
$data = Request::param();
$data['create_time'] = date('Y-m-d H:i:s');
$data['tid'] = $this->getTenantId();
$id = FilesCategory::insertGetId($data);
// 记录操作日志
$this->logSuccess('文件管理', '创建文件分组', ['id' => $id]);
return json([
'code' => 200,
'msg' => '新建文件分组成功',
'data' => [
'id' => $id
]
]);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '创建文件分组', $e->getMessage());
return json([
'code' => 500,
'msg' => '新建文件分组失败: ' . $e->getMessage()
]);
}
}
//重命名文件分组
public function renameFileCate($id)
{
try {
$data = Request::param();
$result = FilesCategory::where('id', $id)
->where('tid', $this->getTenantId())
->update(['name' => $data['name']]);
// 记录操作日志
$this->logSuccess('文件管理', '重命名文件分组', ['id' => $id]);
return json([
'code' => 200,
'msg' => '重命名文件分组成功'
]);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '重命名文件分组', $e->getMessage());
return json([
'code' => 500,
'msg' => '重命名文件分组失败: ' . $e->getMessage()
]);
}
}
//删除文件分组
public function deleteFileCate($id)
{
try {
// 检查分组里是否有关联文件
$fileCount = Files::where('cate', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->count();
if ($fileCount > 0) {
return json([
'code' => 400,
'msg' => '该分组下还有 ' . $fileCount . ' 个文件,请先删除分组内文件!'
]);
}
$result = FilesCategory::where('id', $id)
->where('tid', $this->getTenantId())
->update(['delete_time' => date('Y-m-d H:i:s')]);
// 记录操作日志
$this->logSuccess('文件管理', '删除文件分组', ['id' => $id]);
return json([
'code' => 200,
'msg' => '删除文件分组成功'
]);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '删除文件分组', $e->getMessage());
return json([
'code' => 500,
'msg' => '删除文件分组失败: ' . $e->getMessage()
]);
}
}
//获取分类文件
public function getCateFiles(int $id)
{
try {
$page = Request::param('page/d', 1);
$pageSize = Request::param('pageSize/d', 10);
$keyword = Request::param('keyword/s', '');
$query = Files::where('cate', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null);
if ($keyword) {
$query->whereLike('name', "%{$keyword}%");
}
// 获取总条数
$total = $query->count();
$list = $query->page($page, $pageSize)
->order('create_time', 'desc')
->select();
// 格式化文件信息
foreach ($list as &$file) {
$file['createTime'] = $file['create_time'];
$file['groupId'] = $file['cate'];
$file['url'] = $file['src'];
}
return json([
'code' => 200,
'msg' => 'success',
'data' => [
'list' => $list,
'total' => $total,
'page' => $page,
'pageSize' => $pageSize,
'categoryId' => $id
]
]);
} catch (\Exception $e) {
return json([
'code' => 500,
'msg' => '获取分类文件失败: ' . $e->getMessage()
]);
}
}
// 文件上传
public function uploadFile()
{
try {
$file = Request::file('file');
if (!$file) {
return json(['code' => 400, 'msg' => '请选择要上传的文件']);
}
// 验证文件大小和类型
$maxSize = 50 * 1024 * 1024; // 50MB
$fileExt = strtolower($file->getOriginalExtension());
if ($file->getSize() > $maxSize) {
return json(['code' => 400, 'msg' => '文件大小不能超过50MB']);
}
// 计算文件MD5
$fileMd5 = md5_file($file->getRealPath());
// 检查是否已存在相同文件
$existFile = Files::where('md5', $fileMd5)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->find();
if ($existFile) {
return json([
'code' => 201,
'msg' => '文件已存在',
'data' => [
'url' => $existFile['src'],
'id' => $existFile['id'],
'name' => $existFile['name']
]
]);
}
// 确定文件类型
$fileType = 2; // 默认为文件
foreach ($this->allowedExtensions as $type => $extensions) {
if (in_array($fileExt, $extensions)) {
$fileType = $this->fileTypes[$type];
break;
}
}
$cate = Request::param('cate/d', 0);
// 生成按日期分类的目录结构
$datePath = date('Y/m/d');
$saveName = $datePath . '/' . uniqid() . '.' . $fileExt;
$fullPath = Filesystem::disk('public')->putFileAs('uploads', $file, $saveName);
$fileUrl = '/storage/' . str_replace('\\', '/', $fullPath);
// 获取当前登录用户ID
$userId = Request::middleware('user_id', '');
// 保存文件信息到数据库
$fileData = [
'name' => $file->getOriginalName(),
'type' => $fileType,
'cate' => $cate,
'size' => $file->getSize(),
'src' => $fileUrl,
'md5' => $fileMd5,
'uploader' => $userId,
'tid' => $this->getTenantId(),
'create_time' => date('Y-m-d H:i:s'),
];
$fileId = Files::insertGetId($fileData);
// 记录操作日志
$this->logSuccess('文件管理', '上传文件', ['id' => $fileId]);
return json([
'code' => 200,
'msg' => '上传成功',
'data' => [
'url' => $fileUrl,
'id' => $fileId,
'name' => $fileData['name']
]
]);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '上传文件', $e->getMessage());
return json([
'code' => 500,
'msg' => '上传失败: ' . $e->getMessage()
]);
}
}
// 更新文件信息
public function updateFile($id)
{
try {
$data = Request::only(['name', 'cate']);
if (empty($data)) {
return json(['code' => 400, 'msg' => '无更新数据']);
}
$data['update_time'] = date('Y-m-d H:i:s');
$result = Files::where('id', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->update($data);
if ($result) {
// 记录操作日志
$this->logSuccess('文件管理', '更新文件', ['id' => $id]);
return json(['code' => 200, 'msg' => '更新成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '更新文件', $e->getMessage());
return json(['code' => 500, 'msg' => '更新失败: ' . $e->getMessage()]);
}
}
// 删除文件
public function deleteFile($id)
{
try {
// 先获取文件信息
$file = Files::where('id', $id)
->where('tid', $this->getTenantId())
->find();
if (!$file) {
return json(['code' => 404, 'msg' => '文件不存在']);
}
$result = Files::where('id', $id)
->where('tid', $this->getTenantId())
->update(['delete_time' => date('Y-m-d H:i:s')]);
if ($result) {
// 记录操作日志
$this->logSuccess('文件管理', '删除文件', ['id' => $id]);
return json(['code' => 200, 'msg' => '删除成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '删除文件', $e->getMessage());
return json(['code' => 500, 'msg' => '删除失败: ' . $e->getMessage()]);
}
}
//永久删除文件
public function deleteFilePermanently($id)
{
try {
// 先获取文件信息
$file = Files::where('id', $id)
->where('tid', $this->getTenantId())
->find();
if (!$file) {
return json(['code' => 404, 'msg' => '文件不存在']);
}
// 删除服务器上的文件
if ($file['src']) {
$this->deleteFileFromServer($file['src']);
}
$result = Files::where('id', $id)
->where('tid', $this->getTenantId())
->update(['delete_time' => date('Y-m-d H:i:s')]);
if ($result) {
// 记录操作日志
$this->logSuccess('文件管理', '永久删除文件', ['id' => $id]);
return json(['code' => 200, 'msg' => '永久删除成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '永久删除文件', $e->getMessage());
return json(['code' => 500, 'msg' => '永久删除失败: ' . $e->getMessage()]);
}
}
// 下载文件
public function download($id)
{
try {
$file = Files::where('id', $id)
->where('tid', $this->getTenantId())
->where('delete_time', null)
->find();
if (!$file) {
return json(['code' => 404, 'msg' => '文件不存在']);
}
$filePath = public_path() . $file['src'];
if (!file_exists($filePath)) {
return json(['code' => 404, 'msg' => '文件不存在']);
}
return download($filePath, $file['name']);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '下载文件', $e->getMessage());
return json(['code' => 500, 'msg' => '下载失败: ' . $e->getMessage()]);
}
}
// 移动文件
public function moveFile($id)
{
try {
$cate = Request::param('cate/d', 0);
$result = Files::where('id', $id)
->where('tid', $this->getTenantId())
->update(['cate' => $cate]);
if ($result) {
// 记录操作日志
$this->logSuccess('文件管理', '移动文件', ['id' => $id]);
return json(['code' => 200, 'msg' => '移动成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
// 记录失败日志
$this->logFail('文件管理', '移动文件', $e->getMessage());
return json(['code' => 500, 'msg' => '移动失败: ' . $e->getMessage()]);
}
}
//删除服务器上文件
private function deleteFileFromServer($fileUrl)
{
// 去掉开头的 /storage/,得到相对路径
$relativePath = ltrim($fileUrl, '/');
if (strpos($relativePath, 'storage/') === 0) {
$relativePath = substr($relativePath, 8); // 去掉 'storage/' 部分
}
// 获取实际服务器路径
$fullPath = root_path() . 'public/storage/' . $relativePath;
if (file_exists($fullPath)) {
unlink($fullPath);
}
}
// 批量删除文件
public function batchDeleteFiles()
{
try {
$ids = Request::param('ids/a', []);
if (empty($ids)) {
return json(['code' => 400, 'msg' => '请选择要删除的文件']);
}
foreach ($ids as $id) {
$file = Files::where('id', $id)
->where('tid', $this->getTenantId())
->find();
if ($file && $file['src']) {
$this->deleteFileFromServer($file['src']);
}
}
$result = Files::where('id', 'in', $ids)
->where('tid', $this->getTenantId())
->update(['delete_time' => date('Y-m-d H:i:s')]);
if ($result) {
$this->logSuccess('文件管理', '批量删除文件', ['ids' => $ids]);
return json(['code' => 200, 'msg' => '批量删除成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
$this->logFail('文件管理', '批量删除文件', $e->getMessage());
return json(['code' => 500, 'msg' => '批量删除失败: ' . $e->getMessage()]);
}
}
// 批量彻底删除文件
public function batchDeleteFilesPermanently()
{
try {
$ids = Request::param('ids/a', []);
if (empty($ids)) {
return json(['code' => 400, 'msg' => '请选择要彻底删除的文件']);
}
foreach ($ids as $id) {
$file = Files::where('id', $id)
->where('tid', $this->getTenantId())
->find();
if ($file && $file['src']) {
$this->deleteFileFromServer($file['src']);
}
}
$result = Files::where('id', 'in', $ids)
->where('tid', $this->getTenantId())
->force(true)
->update(['delete_time' => date('Y-m-d H:i:s')])
->delete();
if ($result) {
$this->logSuccess('文件管理', '批量彻底删除文件', ['ids' => $ids]);
return json(['code' => 200, 'msg' => '批量彻底删除成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
$this->logFail('文件管理', '批量彻底删除文件', $e->getMessage());
return json(['code' => 500, 'msg' => '批量彻底删除失败: ' . $e->getMessage()]);
}
}
// 批量移动文件
public function batchMoveFiles()
{
try {
$ids = Request::param('ids/a', []);
$cate = Request::param('cate/d', 0);
if (empty($ids)) {
return json(['code' => 400, 'msg' => '请选择要移动的文件']);
}
$result = Files::where('id', 'in', $ids)
->where('tid', $this->getTenantId())
->update(['cate' => $cate]);
if ($result) {
$this->logSuccess('文件管理', '批量移动文件', ['ids' => $ids, 'cate' => $cate]);
return json(['code' => 200, 'msg' => '批量移动成功']);
}
return json(['code' => 404, 'msg' => '文件不存在']);
} catch (\Exception $e) {
$this->logFail('文件管理', '批量移动文件', $e->getMessage());
return json(['code' => 500, 'msg' => '批量移动失败: ' . $e->getMessage()]);
}
}
}