<?php
namespace Boab\CmsBundle\Controller;
use Boab\CmsBundle\Repository\ContentRepositoryInterface;
use Boab\CmsBundle\Filesystem\FilesystemManager;
use Intervention\Image\ImageManager;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\StreamedResponse;
use Symfony\Component\HttpKernel\Exception\NotFoundHttpException;
use Symfony\Component\HttpFoundation\Response;
class DownloadController
{
private FilesystemManager $filesystemManager;
public function __construct(FilesystemManager $filesystemManager)
{
$this->filesystemManager = $filesystemManager;
}
public function download(Request $request, string $fileName)
{
$filesystems = $this->filesystemManager->getFilesystems();
$crop = $this->parseSizeParameter($request);
foreach ($filesystems as $filesystem) {
if (!$filesystem->has($fileName)) {
continue;
}
// Get the file extension
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
// Exclude non-image file formats from caching
if ($crop && !$this->isImageExtension($extension)) {
$crop = null;
}
// Get the file stream
$fileStream = $filesystem->readStream($fileName);
// If crop parameters are provided, perform the image cropping
if ($crop) {
$croppedFileName = $this->getCropFilename($fileName, $crop);
if($filesystem->has($croppedFileName)){
$fileStream2 = $filesystem->readStream($fileName);
return $this->createStreamResponse($fileStream2, $extension);
}
// Save the cropped image to the same filesystem
$fileStream = $this->getCroppedStream($fileStream, $crop);
$filesystem->writeStream($croppedFileName, $fileStream);
return $this->createStreamResponse($fileStream, $extension);
}
// Set the appropriate content type based on the file extension
return $this->createStreamResponse($fileStream, $extension);
}
// If the file is not found in any filesystem, throw a NotFoundHttpException
throw new NotFoundHttpException('File not found.');
}
private function createStreamResponse($fileStream, $extension, string $fileName=""):Response
{
// Set the appropriate content type based on the file extension
$contentType = $this->getContentType($extension);
$response = new StreamedResponse(function() use ($fileStream, $fileName) {
$outputStream = fopen('php://output', 'wb');
//$fileStream = $cloudStorageAudio->readStream($audio->getPrimaryFile(), false);
stream_copy_to_stream($fileStream, $outputStream);
});
$response->headers->set('Content-Type', $contentType);
return $response;
}
private function getCroppedStream($stream, array $crop)
{
$imageManager = new ImageManager();
$image = $imageManager->make($stream);
//$image->crop($crop['width'], $crop['height'], $crop['x'], $crop['y']);
$image->resize($crop['width'], $crop['height'], function ($constraint) {
$constraint->aspectRatio();
$constraint->upsize();
});
$stream = $image->stream()->detach();
return $stream;
}
private function getCropFilename(string $filename, array $crop): string
{
if ($crop) {
$cropFilename = pathinfo($filename, PATHINFO_FILENAME) . '_' . $crop['width'] . 'x' . $crop['height'] . '.' . pathinfo($filename, PATHINFO_EXTENSION);
return $cropFilename;
}
return $filename;
}
private function isImageExtension(string $extension): bool
{
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif']; // Add more image extensions as needed
return in_array(strtolower($extension), $imageExtensions, true);
}
private function parseSizeParameter(Request $request): ?array
{
// Get the size from the query parameters
$size = $request->query->get('size');
if (!$size) {
return null;
}
// Split the size parameter into width and height
$parts = explode('x', $size);
// If both width and height are specified, return the crop parameters
if (count($parts) === 2) {
return [
'x' => 0,
'y' => 0,
'width' => (int) $parts[0],
'height' => (int) $parts[1],
];
}
return null;
}
private function getContentType(string $extension): string
{
$mappings = [
'pdf' => 'application/pdf',
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
// Add more mappings as needed
];
// Check if the extension mapping exists, otherwise default to 'application/octet-stream'
return $mappings[$extension] ?? 'application/octet-stream';
}
}