entityManager->getRepository(TaskDocument::class)->find($id); if (null === $document) { throw new NotFoundHttpException('Document not found.'); } $mimeType = $document->getMimeType() ?? 'application/octet-stream'; // Inline for images (except SVG) and PDFs, attachment for everything else. // SVG is always attachment to prevent XSS via embedded JavaScript. $inline = 'image/svg+xml' !== $mimeType && (str_starts_with($mimeType, 'image/') || 'application/pdf' === $mimeType); $disposition = $inline ? ResponseHeaderBag::DISPOSITION_INLINE : ResponseHeaderBag::DISPOSITION_ATTACHMENT; return $document->isShareLink() ? $this->streamFromShare($document, $mimeType, $disposition) : $this->streamFromDisk($document, $mimeType, $disposition); } private function streamFromDisk(TaskDocument $document, string $mimeType, string $disposition): BinaryFileResponse { $filePath = $this->uploadDir.'/'.$document->getFileName(); if (!file_exists($filePath)) { throw new NotFoundHttpException('File not found on disk.'); } $response = new BinaryFileResponse($filePath); $response->setContentDisposition($disposition, (string) $document->getOriginalName()); $response->headers->set('Content-Type', $mimeType); $response->headers->set('X-Content-Type-Options', 'nosniff'); return $response; } private function streamFromShare(TaskDocument $document, string $mimeType, string $disposition): StreamedResponse { try { $stream = $this->fileSource->read((string) $document->getSharePath()); } catch (ShareNotConfiguredException) { throw new NotFoundHttpException('Share not configured.'); } catch (ShareConnectionException) { throw new NotFoundHttpException('File not found on the share.'); } $response = new StreamedResponse(function () use ($stream): void { if (is_resource($stream)) { fpassthru($stream); fclose($stream); } }); $response->headers->set('Content-Type', $mimeType); $response->headers->set('Content-Disposition', HeaderUtils::makeDisposition($disposition, (string) $document->getOriginalName())); $response->headers->set('X-Content-Type-Options', 'nosniff'); return $response; } }