|
|
@@ -4,7 +4,8 @@ namespace Longyi\ImageUpload\Http\Controllers\Admin;
|
|
|
|
|
|
use App\Http\Controllers\Controller;
|
|
|
use Illuminate\Http\Request;
|
|
|
-use Illuminate\Support\Facades\Storage;
|
|
|
+use Longyi\ImageUpload\Models\ImageFolder;
|
|
|
+use Longyi\ImageUpload\Models\ImageUpload as ImageUploadModel;
|
|
|
use Longyi\ImageUpload\Services\ImageUploadService;
|
|
|
use Exception;
|
|
|
|
|
|
@@ -77,6 +78,29 @@ class ImageUploadController extends Controller
|
|
|
|
|
|
$results = $this->imageUploadService->uploadMultiple($files, $directory);
|
|
|
|
|
|
+ // 解析 folder_id:如果传了 directory,按目录名查找文件夹
|
|
|
+ $folderId = 0;
|
|
|
+ if (! empty($directory)) {
|
|
|
+ $folder = ImageFolder::where('name', $directory)->first();
|
|
|
+ $folderId = $folder ? $folder->id : 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 将上传成功的图片记录写入 image_uploads 表
|
|
|
+ foreach ($results as $result) {
|
|
|
+ if (! empty($result['success'])) {
|
|
|
+ ImageUploadModel::create([
|
|
|
+ 'folder_id' => $folderId,
|
|
|
+ 'original_name' => $result['original_name'] ?? '',
|
|
|
+ 'file_name' => basename($result['path'] ?? ''),
|
|
|
+ 'file_path' => $result['path'] ?? '',
|
|
|
+ 'file_url' => $result['url'] ?? '',
|
|
|
+ 'mime_type' => $result['mime_type'] ?? '',
|
|
|
+ 'file_size' => $result['size'] ?? 0,
|
|
|
+ 'disk' => $result['disk'] ?? 's3',
|
|
|
+ ]);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
$successCount = count(array_filter($results, fn($r) => $r['success'] ?? false));
|
|
|
$failedCount = count($results) - $successCount;
|
|
|
|
|
|
@@ -97,7 +121,7 @@ class ImageUploadController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Delete an image.
|
|
|
+ * Delete an image (S3 + database record).
|
|
|
*
|
|
|
* @param Request $request
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
@@ -113,19 +137,16 @@ class ImageUploadController extends Controller
|
|
|
$path = $request->input('path');
|
|
|
$disk = $request->input('disk');
|
|
|
|
|
|
+ // 删除 S3 文件
|
|
|
$deleted = $this->imageUploadService->delete($path, $disk);
|
|
|
|
|
|
- if ($deleted) {
|
|
|
- return response()->json([
|
|
|
- 'success' => true,
|
|
|
- 'message' => __('Image deleted successfully'),
|
|
|
- ]);
|
|
|
- } else {
|
|
|
- return response()->json([
|
|
|
- 'success' => false,
|
|
|
- 'message' => __('Failed to delete image'),
|
|
|
- ], 422);
|
|
|
- }
|
|
|
+ // 同时删除数据库记录
|
|
|
+ ImageUploadModel::where('file_path', $path)->delete();
|
|
|
+
|
|
|
+ return response()->json([
|
|
|
+ 'success' => true,
|
|
|
+ 'message' => __('Image deleted successfully'),
|
|
|
+ ]);
|
|
|
} catch (Exception $e) {
|
|
|
return response()->json([
|
|
|
'success' => false,
|
|
|
@@ -166,7 +187,7 @@ class ImageUploadController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Get folders list.
|
|
|
+ * Get folders list (from database).
|
|
|
*
|
|
|
* @param Request $request
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
@@ -174,29 +195,17 @@ class ImageUploadController extends Controller
|
|
|
public function getFolders(Request $request)
|
|
|
{
|
|
|
try {
|
|
|
- $disk = config('image_upload.default_disk', 's3');
|
|
|
- $basePath = config('image_upload.upload_directory', 'images/uploads');
|
|
|
-
|
|
|
- $folders = [];
|
|
|
- $storage = Storage::disk($disk);
|
|
|
-
|
|
|
- // Get all directories under base path
|
|
|
- $allDirs = $storage->allDirectories($basePath);
|
|
|
-
|
|
|
- foreach ($allDirs as $dir) {
|
|
|
- $relativePath = str_replace($basePath . '/', '', $dir);
|
|
|
- if (! empty($relativePath)) {
|
|
|
- $folders[] = [
|
|
|
- 'path' => $dir,
|
|
|
- 'name' => $relativePath,
|
|
|
- ];
|
|
|
- }
|
|
|
- }
|
|
|
+ $folders = ImageFolder::orderBy('created_at', 'desc')->get()->map(function ($folder) {
|
|
|
+ return [
|
|
|
+ 'id' => $folder->id,
|
|
|
+ 'name' => $folder->name,
|
|
|
+ 'path' => $folder->path,
|
|
|
+ ];
|
|
|
+ });
|
|
|
|
|
|
return response()->json([
|
|
|
'success' => true,
|
|
|
- 'data' => [
|
|
|
- 'base_path' => $basePath,
|
|
|
+ 'data' => [
|
|
|
'folders' => $folders,
|
|
|
],
|
|
|
]);
|
|
|
@@ -209,7 +218,7 @@ class ImageUploadController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Create a folder.
|
|
|
+ * Create a folder (database only, no S3).
|
|
|
*
|
|
|
* @param Request $request
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
@@ -218,34 +227,39 @@ class ImageUploadController extends Controller
|
|
|
{
|
|
|
try {
|
|
|
$request->validate([
|
|
|
- 'folder_name' => 'required|string|max:255',
|
|
|
+ 'folder_name' => 'required|string|max:255',
|
|
|
'parent_folder' => 'nullable|string',
|
|
|
]);
|
|
|
|
|
|
- $folderName = $request->input('folder_name');
|
|
|
- $parentFolder = $request->input('parent_folder', '');
|
|
|
+ $folderName = trim($request->input('folder_name'));
|
|
|
+ $parentFolder = trim($request->input('parent_folder', ''));
|
|
|
|
|
|
- $disk = config('image_upload.default_disk', 's3');
|
|
|
- $basePath = config('image_upload.upload_directory', 'uploads');
|
|
|
- $folderPath = $basePath;
|
|
|
+ // 检查同名文件夹
|
|
|
+ $exists = ImageFolder::where('name', $folderName)
|
|
|
+ ->where('parent_id', 0)
|
|
|
+ ->exists();
|
|
|
|
|
|
- if (! empty($parentFolder)) {
|
|
|
- $folderPath .= '/' . trim($parentFolder, '/');
|
|
|
+ if ($exists) {
|
|
|
+ return response()->json([
|
|
|
+ 'success' => false,
|
|
|
+ 'message' => __('Folder already exists'),
|
|
|
+ ], 422);
|
|
|
}
|
|
|
- $folderPath .= '/' . trim($folderName, '/');
|
|
|
- // For S3, create a placeholder file to "create" the folder
|
|
|
- $storage = Storage::disk($disk);
|
|
|
|
|
|
- if (! $storage->exists($folderPath)) {
|
|
|
- $storage->put($folderPath . '/.gitkeep', '');
|
|
|
- }
|
|
|
+ $basePath = config('image_upload.upload_directory', 'uploads');
|
|
|
+ $folder = ImageFolder::create([
|
|
|
+ 'name' => $folderName,
|
|
|
+ 'parent_id' => 0,
|
|
|
+ 'path' => $basePath . '/' . $folderName,
|
|
|
+ ]);
|
|
|
|
|
|
return response()->json([
|
|
|
'success' => true,
|
|
|
'message' => __('Folder created successfully'),
|
|
|
- 'data' => [
|
|
|
- 'path' => $folderPath,
|
|
|
- 'name' => trim($folderName, '/'),
|
|
|
+ 'data' => [
|
|
|
+ 'id' => $folder->id,
|
|
|
+ 'name' => $folder->name,
|
|
|
+ 'path' => $folder->path,
|
|
|
],
|
|
|
]);
|
|
|
} catch (Exception $e) {
|
|
|
@@ -257,7 +271,7 @@ class ImageUploadController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Delete a folder.
|
|
|
+ * Delete a folder (database + related images on S3).
|
|
|
*
|
|
|
* @param Request $request
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
@@ -266,17 +280,27 @@ class ImageUploadController extends Controller
|
|
|
{
|
|
|
try {
|
|
|
$request->validate([
|
|
|
- 'folder_path' => 'required|string',
|
|
|
+ 'folder_id' => 'required|integer',
|
|
|
]);
|
|
|
|
|
|
- $folderPath = $request->input('folder_path');
|
|
|
- $disk = config('image_upload.default_disk', 's3');
|
|
|
- $storage = Storage::disk($disk);
|
|
|
-
|
|
|
- if ($storage->exists($folderPath)) {
|
|
|
- $storage->deleteDirectory($folderPath);
|
|
|
+ $folderId = $request->input('folder_id');
|
|
|
+ $folder = ImageFolder::findOrFail($folderId);
|
|
|
+
|
|
|
+ // 删除该文件夹下所有图片的 S3 文件和数据库记录
|
|
|
+ $images = ImageUploadModel::where('folder_id', $folderId)->get();
|
|
|
+ foreach ($images as $image) {
|
|
|
+ // 从 S3 删除图片文件
|
|
|
+ try {
|
|
|
+ $this->imageUploadService->delete($image->file_path, $image->disk);
|
|
|
+ } catch (\Exception $e) {
|
|
|
+ // S3 删除失败不影响数据库删除
|
|
|
+ }
|
|
|
+ $image->delete();
|
|
|
}
|
|
|
|
|
|
+ // 删除文件夹记录
|
|
|
+ $folder->delete();
|
|
|
+
|
|
|
return response()->json([
|
|
|
'success' => true,
|
|
|
'message' => __('Folder deleted successfully'),
|
|
|
@@ -290,7 +314,7 @@ class ImageUploadController extends Controller
|
|
|
}
|
|
|
|
|
|
/**
|
|
|
- * Get images in a folder.
|
|
|
+ * Get images in a folder (from database).
|
|
|
*
|
|
|
* @param Request $request
|
|
|
* @return \Illuminate\Http\JsonResponse
|
|
|
@@ -298,37 +322,31 @@ class ImageUploadController extends Controller
|
|
|
public function getImages(Request $request)
|
|
|
{
|
|
|
try {
|
|
|
- $folderPath = $request->input('folder_path', '');
|
|
|
- $disk = config('image_upload.default_disk', 's3');
|
|
|
- $basePath = config('image_upload.upload_directory', 'images/uploads');
|
|
|
+ $folderId = $request->input('folder_id', 0);
|
|
|
|
|
|
- $searchPath = $basePath;
|
|
|
- if (! empty($folderPath)) {
|
|
|
- $searchPath .= '/' . trim($folderPath, '/');
|
|
|
- }
|
|
|
+ $query = ImageUploadModel::orderBy('created_at', 'desc');
|
|
|
|
|
|
- $storage = Storage::disk($disk);
|
|
|
- $files = $storage->files($searchPath);
|
|
|
-
|
|
|
- $images = [];
|
|
|
- $allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'webp', 'svg'];
|
|
|
-
|
|
|
- foreach ($files as $file) {
|
|
|
- $extension = strtolower(pathinfo($file, PATHINFO_EXTENSION));
|
|
|
- if (in_array($extension, $allowedExtensions)) {
|
|
|
- $images[] = [
|
|
|
- 'path' => $file,
|
|
|
- 'name' => basename($file),
|
|
|
- 'url' => $storage->url($file),
|
|
|
- 'size' => $storage->size($file),
|
|
|
- 'last_modified' => $storage->lastModified($file),
|
|
|
- ];
|
|
|
- }
|
|
|
+ if ($folderId > 0) {
|
|
|
+ $query->where('folder_id', $folderId);
|
|
|
+ } else {
|
|
|
+ $query->where('folder_id', 0);
|
|
|
}
|
|
|
|
|
|
+ $images = $query->get()->map(function ($image) {
|
|
|
+ return [
|
|
|
+ 'id' => $image->id,
|
|
|
+ 'path' => $image->file_path,
|
|
|
+ 'name' => $image->original_name,
|
|
|
+ 'url' => $image->file_url,
|
|
|
+ 'size' => $image->file_size,
|
|
|
+ 'mime_type' => $image->mime_type,
|
|
|
+ 'last_modified' => $image->updated_at->timestamp,
|
|
|
+ ];
|
|
|
+ });
|
|
|
+
|
|
|
return response()->json([
|
|
|
'success' => true,
|
|
|
- 'data' => $images,
|
|
|
+ 'data' => $images,
|
|
|
]);
|
|
|
} catch (Exception $e) {
|
|
|
return response()->json([
|