diff --git a/app/Http/Controllers/User/ImageController.php b/app/Http/Controllers/User/ImageController.php index d7acdde8..a0727536 100644 --- a/app/Http/Controllers/User/ImageController.php +++ b/app/Http/Controllers/User/ImageController.php @@ -15,6 +15,7 @@ use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; use Illuminate\View\View; use League\Flysystem\FilesystemException; +use Symfony\Component\HttpFoundation\StreamedResponse; class ImageController extends Controller { @@ -28,41 +29,43 @@ class ImageController extends Controller /** @var User $user */ $user = Auth::user(); - $images = $user->images()->when($request->query('order') ?: 'newest', function (Builder $builder, $order) { - switch ($order) { - case 'earliest': - $builder->orderBy('created_at'); - break; - case 'utmost': - $builder->orderByDesc('size'); - break; - case 'least': - $builder->orderBy('size'); - break; - default: - $builder->latest(); - } - })->when($request->query('visibility') ?: 'all', function (Builder $builder, $visibility) { - switch ($visibility) { - case 'public': - $builder->where('permission', ImagePermission::Public); - break; - case 'private': - $builder->where('permission', ImagePermission::Private); - break; - } - })->when($request->query('keyword'), function (Builder $builder, $keyword) { - $builder->whereRaw("concat(IFNULL(origin_name,''),IFNULL(alias_name,'')) like ?", ["%{$keyword}%"]); - })->when((int) $request->query('album_id'), function (Builder $builder, $albumId) { - $builder->where('album_id', $albumId); - }, function (Builder $builder) { - $builder->whereNull('album_id'); - })->paginate(40); + $images = Image::with('strategy') + ->where('user_id', $user->id) + ->when($request->query('order') ?: 'newest', function (Builder $builder, $order) { + switch ($order) { + case 'earliest': + $builder->orderBy('created_at'); + break; + case 'utmost': + $builder->orderByDesc('size'); + break; + case 'least': + $builder->orderBy('size'); + break; + default: + $builder->latest(); + } + })->when($request->query('visibility') ?: 'all', function (Builder $builder, $visibility) { + switch ($visibility) { + case 'public': + $builder->where('permission', ImagePermission::Public); + break; + case 'private': + $builder->where('permission', ImagePermission::Private); + break; + } + })->when($request->query('keyword'), function (Builder $builder, $keyword) { + $builder->whereRaw("concat(IFNULL(origin_name,''),IFNULL(alias_name,'')) like ?", ["%{$keyword}%"]); + })->when((int) $request->query('album_id'), function (Builder $builder, $albumId) { + $builder->where('album_id', $albumId); + }, function (Builder $builder) { + $builder->whereNull('album_id'); + })->paginate(40); $images->getCollection()->each(function (Image $image) { $image->human_date = $image->created_at->diffForHumans(); $image->date = $image->created_at->format('Y-m-d H:i:s'); - $image->append(['url', 'filename', 'links'])->setVisible([ - 'id', 'filename', 'url', 'human_date', 'date', 'size', 'width', 'height', 'links' + $image->append(['url', 'thumb_url', 'filename', 'links'])->setVisible([ + 'id', 'filename', 'url', 'thumb_url', 'human_date', 'date', 'size', 'width', 'height', 'links' ]); }); return $this->success('success', compact('images')); @@ -73,30 +76,56 @@ class ImageController extends Controller /** @var User $user */ $user = Auth::user(); /** @var Image $image */ - if (! $image = $user->images()->find($request->route('id'))) { + if (!$image = $user->images()->find($request->route('id'))) { return $this->error('未找到该图片'); } $image->strategy->setVisible(['name']); $image->album?->setVisible(['name']); - $image->append(['url', 'filename', 'links'])->setVisible([ - 'id', 'filename', 'origin_name', 'url', 'width', 'height', 'size', 'mimetype', 'md5', 'sha1', 'permission', - 'strategy', 'album', 'uploaded_ip', 'links', 'created_at' + $image->append(['url', 'thumb_url', 'filename', 'links'])->setVisible([ + 'id', 'filename', 'origin_name', 'url', 'thumb_url', 'width', 'height', 'size', 'mimetype', 'md5', 'sha1', + 'permission', 'strategy', 'album', 'uploaded_ip', 'links', 'created_at' ]); return $this->success('success', compact('image')); } - public function output(Request $request) + public function output(Request $request): StreamedResponse { /** @var Image $image */ - $image = Image::query()->where('key', $request->route('key'))->firstOr(fn() => abort(404)); + $image = Image::query() + ->where('key', $request->route('key')) + ->where('extension', $request->route('extension')) + ->firstOr(fn() => abort(404)); + try { + $contents = $image->filesystem()->read($image->pathname); + } catch (FilesystemException $e) { + abort(404); + } + return \response()->stream(function () use ($contents) { + echo $contents; + }, headers: ['Content-type' => $image->mimetype]); + } + + public function thumbnail(Request $request) + { + /** @var Image $image */ + $image = Image::query() + ->where('key', $request->route('key')) + ->where('extension', $request->route('extension')) + ->firstOr(fn() => abort(404)); try { $stream = $image->filesystem()->readStream($image->pathname); } catch (FilesystemException $e) { abort(404); } $img = \Intervention\Image\Facades\Image::make($stream); - // ... - return $img->response(quality: 100); + $width = $image->width; + $height = $image->height; + if ($width > 600 && $height > 600) { + $width = $width / 2; + $height = $height / 2; + } + $img->fit((int)$width, (int)$height, fn($constraint) => $constraint->upsize()); + return $img->response(); } public function permission(Request $request): Response @@ -105,7 +134,7 @@ class ImageController extends Controller $user = Auth::user(); $permission = $request->input('permission'); $permissions = ['public' => ImagePermission::Public, 'private' => ImagePermission::Private]; - if (! in_array($permission, array_keys($permissions))) { + if (!in_array($permission, array_keys($permissions))) { return $this->error('设置失败'); } $user->images()->whereIn('id', (array) $request->input('ids'))->update([ diff --git a/app/Models/Image.php b/app/Models/Image.php index b507b079..1db577c6 100644 --- a/app/Models/Image.php +++ b/app/Models/Image.php @@ -34,6 +34,7 @@ use League\Flysystem\Filesystem; * @property integer $width * @property integer $height * @property string $url + * @property string $thumb_url * @property Collection $links * @property int $permission * @property boolean $is_unhealthy @@ -128,6 +129,13 @@ class Image extends Model }); } + public function thumbUrl(): Attribute + { + return new Attribute(function () { + return $this->url.'!thumbnail'; + }); + } + public function links(): Attribute { return new Attribute(fn() => collect([ diff --git a/resources/views/images.blade.php b/resources/views/images.blade.php index d70bc009..6be1ed6f 100644 --- a/resources/views/images.blade.php +++ b/resources/views/images.blade.php @@ -105,7 +105,7 @@

__date__

- __name__ + __name__ @@ -225,7 +225,7 @@ const $photos = $(IMAGES_GRID); const $drawer = $("#drawer"); const $drawerMask = $('#drawer-mask'); - const viewer = new Viewer(document.getElementById('images-grid'), {}); + const viewer = new Viewer(document.getElementById('images-grid'), {url: 'data-original'}); const drawer = { open(title, content, callback) { $drawerMask.fadeIn(); @@ -273,6 +273,7 @@ .replace(/__human_date__/g, images[i].human_date) .replace(/__date__/g, images[i].date) .replace(/__url__/g, images[i].url) + .replace(/__thumb_url__/g, images[i].thumb_url) .replace(/__width__/g, images[i].width) .replace(/__height__/g, images[i].height) .replace(/__json__/g, JSON.stringify(images[i])) diff --git a/routes/image.php b/routes/image.php new file mode 100644 index 00000000..4c12c89e --- /dev/null +++ b/routes/image.php @@ -0,0 +1,16 @@ +get(GroupConfigKey::AcceptedFileSuffixes); +Route::middleware('cache.headers:public;max_age=2628000;etag')->group(function () use ($extensions) { + Route::any('{key}.{extension}', [ + ImageController::class, 'output', + ])->where('extension', implode('|', $extensions)); + Route::any('{key}.{extension}!thumbnail', [ + ImageController::class, 'thumbnail', + ])->where('extension', implode('|', $extensions)); +}); diff --git a/routes/web.php b/routes/web.php index aada8366..c661488c 100644 --- a/routes/web.php +++ b/routes/web.php @@ -37,8 +37,5 @@ Route::group(['middleware' => ['auth']], function () { }); }); -Route::any('{key}.{extension}', [ImageController::class, 'output'])->where('extension', implode('|', [ - 'jpg', 'jpeg', 'gif', 'png', 'apng', 'bmp', 'ico', -])); - +require __DIR__.'/image.php'; require __DIR__.'/auth.php';