resolveFile($baseDir, $name, $allowedExtensions, $downloadName); } public function serveInline( string $baseDir, string $name, array $allowedExtensions, Request $request, ?string $downloadName = null, bool $nosniff = false ): Response { $meta = $this->resolveFile($baseDir, $name, $allowedExtensions, $downloadName); $ifNoneMatch = trim((string) $request->headers->get('If-None-Match', ''), '"'); $ifModifiedSince = (string) $request->headers->get('If-Modified-Since', ''); $imsTime = $ifModifiedSince !== '' ? strtotime($ifModifiedSince) : false; if (($ifNoneMatch !== '' && $ifNoneMatch === $meta['etag']) || ($imsTime !== false && $imsTime >= $meta['mtime']) ) { return response('', 304, $this->notModifiedHeaders($meta)); } $headers = [ 'Content-Type' => $meta['mime'], 'Content-Disposition' => 'inline; filename="'.$meta['download_name'].'"', 'Content-Length' => (string) $meta['size'], 'ETag' => $meta['etag'], 'Last-Modified' => $meta['last_modified'], 'Cache-Control' => 'private, max-age=300', 'X-Content-Type-Options' => 'nosniff', ]; return response(file_get_contents($meta['path']), 200, $headers); } private function resolveFile(string $baseDir, string $name, array $allowedExtensions, ?string $downloadName): array { if ($name !== basename($name)) { throw new HttpException(400, 'Invalid filename'); } $ext = strtolower(pathinfo($name, PATHINFO_EXTENSION)); if (! in_array($ext, $allowedExtensions, true)) { throw new HttpException(404, 'File not found'); } $path = rtrim($baseDir, DIRECTORY_SEPARATOR).DIRECTORY_SEPARATOR.$name; if (! is_file($path)) { throw new HttpException(404, 'File not found'); } $mime = $this->detectMime($path); $mtime = filemtime($path) ?: time(); $size = filesize($path) ?: 0; $etag = md5($name.'|'.$mtime.'|'.$size); $downloadName = $downloadName ? $downloadName.'.'.$ext : $name; return [ 'name' => $name, 'path' => $path, 'mime' => $mime, 'mtime' => $mtime, 'size' => $size, 'etag' => $etag, 'download_name' => $downloadName, 'last_modified' => gmdate('D, d M Y H:i:s', $mtime).' GMT', ]; } private function detectMime(string $path): string { $mime = 'application/octet-stream'; if (function_exists('finfo_open')) { $fi = finfo_open(FILEINFO_MIME_TYPE); if ($fi) { $detected = finfo_file($fi, $path); if ($detected) { $mime = $detected; } finfo_close($fi); } } elseif (function_exists('mime_content_type')) { $mime = mime_content_type($path) ?: $mime; } return $mime; } private function notModifiedHeaders(array $meta): array { return [ 'ETag' => $meta['etag'], 'Last-Modified' => $meta['last_modified'], ]; } }