*/ private const ALLOWED_EXTENSIONS = [ 'jpg', 'jpeg', 'png', 'gif', 'webp', 'bmp', 'tiff', 'zip', 'rar', '7z', 'tar', 'gz', ]; public function __construct( private readonly ArtworkStatsService $stats, ) {} public function __invoke(Request $request, int $id): BinaryFileResponse { $artwork = Artwork::query()->find($id); if (! $artwork) { abort(404); } $filePath = $this->resolveOriginalPath($artwork); $ext = strtolower(ltrim((string) pathinfo($filePath, PATHINFO_EXTENSION), '.')); if ($filePath === '' || ! in_array($ext, self::ALLOWED_EXTENSIONS, true)) { abort(404); } $this->recordDownload($request, $artwork->id); $this->incrementDownloadCountIfAvailable($artwork->id); try { $this->stats->incrementDownloads((int) $artwork->id, 1, defer: false); } catch (\Throwable $exception) { Log::warning('Failed to increment artwork_stats download counter.', [ 'artwork_id' => $artwork->id, 'error' => $exception->getMessage(), ]); } if (! File::isFile($filePath)) { Log::warning('Artwork original file missing for download.', [ 'artwork_id' => $artwork->id, 'ext' => $ext, 'resolved_path' => $filePath, ]); abort(404); } $downloadName = $this->buildDownloadFilename((string) $artwork->file_name, $ext); return response()->download($filePath, $downloadName); } private function resolveOriginalPath(Artwork $artwork): string { $relative = trim((string) $artwork->file_path, '/'); $prefix = trim((string) config('uploads.object_storage.prefix', 'artworks'), '/') . '/original/'; if ($relative !== '' && str_starts_with($relative, $prefix)) { $suffix = substr($relative, strlen($prefix)); $root = rtrim((string) config('uploads.local_originals_root'), DIRECTORY_SEPARATOR); return $root . DIRECTORY_SEPARATOR . str_replace(['/', '\\'], DIRECTORY_SEPARATOR, (string) $suffix); } $hash = strtolower((string) $artwork->hash); $ext = strtolower(ltrim((string) $artwork->file_ext, '.')); if (! $this->isValidHash($hash) || $ext === '') { return ''; } $root = rtrim((string) config('uploads.local_originals_root'), DIRECTORY_SEPARATOR); return $root . DIRECTORY_SEPARATOR . substr($hash, 0, 2) . DIRECTORY_SEPARATOR . substr($hash, 2, 2) . DIRECTORY_SEPARATOR . $hash . '.' . $ext; } private function recordDownload(Request $request, int $artworkId): void { try { $ipAddress = $request->ip(); $ipBinary = $ipAddress ? @inet_pton($ipAddress) : false; ArtworkDownload::query()->create([ 'artwork_id' => $artworkId, 'user_id' => $request->user()?->id, 'ip' => $ipBinary !== false ? $ipBinary : null, 'ip_address' => $ipAddress, 'user_agent' => mb_substr((string) $request->userAgent(), 0, 1024), 'referer' => mb_substr((string) $request->headers->get('referer'), 0, 65535), ]); } catch (\Throwable $exception) { Log::warning('Failed to record artwork download analytics.', [ 'artwork_id' => $artworkId, 'error' => $exception->getMessage(), ]); } } private function incrementDownloadCountIfAvailable(int $artworkId): void { if (! Schema::hasColumn('artworks', 'download_count')) { return; } Artwork::query()->whereKey($artworkId)->increment('download_count'); } private function isValidHash(string $hash): bool { return $hash !== '' && preg_match('/^[a-f0-9]+$/', $hash) === 1; } private function buildDownloadFilename(string $fileName, string $ext): string { $name = trim($fileName); $name = str_replace(['/', '\\'], '-', $name); $name = preg_replace('/[\x00-\x1F\x7F]/', '', $name) ?? ''; $name = preg_replace('/\s+/', ' ', $name) ?? ''; $name = trim((string) $name, ". \t\n\r\0\x0B"); if ($name === '') { $name = 'artwork'; } $baseName = pathinfo($name, PATHINFO_FILENAME); $baseName = trim((string) $baseName, ". \t\n\r\0\x0B"); if ($baseName === '') { $baseName = 'artwork'; } $brandSuffix = $this->downloadBrandSuffix(); if ($brandSuffix !== '' && ! Str::contains(Str::lower($baseName), Str::lower($brandSuffix))) { $baseName .= ' (' . $brandSuffix . ')'; } return $baseName . '.' . $ext; } private function downloadBrandSuffix(): string { $host = (string) parse_url((string) config('app.url'), PHP_URL_HOST); $host = strtolower(trim($host)); $host = preg_replace('/^www\./', '', $host) ?? ''; if ($host === '' || in_array($host, ['localhost', '127.0.0.1'], true) || str_ends_with($host, '.test')) { return 'skinbase.top'; } return $host; } }