122 lines
3.7 KiB
PHP
122 lines
3.7 KiB
PHP
<?php
|
|
|
|
namespace App\Domain\Manga\Infrastructure\Service;
|
|
|
|
use App\Domain\Manga\Domain\Contract\Service\FileServiceInterface;
|
|
use App\Domain\Manga\Domain\Exception\CbzFileNotFoundException;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
|
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
|
|
|
|
readonly class FileService implements FileServiceInterface
|
|
{
|
|
public function __construct(
|
|
private string $cbzStoragePath = '/app/public/cbz'
|
|
) {}
|
|
|
|
public function downloadCbz(string $filePath, string $filename): Response
|
|
{
|
|
if (!$this->cbzExists($filePath)) {
|
|
throw new CbzFileNotFoundException($filePath);
|
|
}
|
|
|
|
$response = new BinaryFileResponse($filePath);
|
|
$response->setContentDisposition(
|
|
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
|
$filename
|
|
);
|
|
$response->headers->set('Content-Type', 'application/x-cbz');
|
|
|
|
return $response;
|
|
}
|
|
|
|
public function createVolumeCbz(array $cbzPaths, string $volumeName): Response
|
|
{
|
|
$tempCbzPath = sys_get_temp_dir() . '/' . $volumeName . '.cbz';
|
|
|
|
$cbz = new \ZipArchive();
|
|
if ($cbz->open($tempCbzPath, \ZipArchive::CREATE) !== true) {
|
|
throw new \RuntimeException('Cannot create CBZ file');
|
|
}
|
|
|
|
$imageCounter = 1;
|
|
|
|
foreach ($cbzPaths as $cbzPath) {
|
|
if (!$this->cbzExists($cbzPath)) {
|
|
continue;
|
|
}
|
|
|
|
$sourceCbz = new \ZipArchive();
|
|
if ($sourceCbz->open($cbzPath) !== true) {
|
|
continue; // Skip if we can't open the CBZ
|
|
}
|
|
|
|
// Extract all images from the current CBZ
|
|
for ($i = 0; $i < $sourceCbz->numFiles; $i++) {
|
|
$fileName = $sourceCbz->getNameIndex($i);
|
|
$fileInfo = $sourceCbz->statIndex($i);
|
|
|
|
// Skip directories and non-image files
|
|
if ($fileInfo['size'] === 0 || !$this->isImageFile($fileName)) {
|
|
continue;
|
|
}
|
|
|
|
// Get the file content
|
|
$imageContent = $sourceCbz->getFromIndex($i);
|
|
if ($imageContent === false) {
|
|
continue;
|
|
}
|
|
|
|
// Get file extension
|
|
$extension = pathinfo($fileName, PATHINFO_EXTENSION);
|
|
|
|
// Create a new filename with proper ordering
|
|
$newFileName = sprintf('%04d.%s', $imageCounter, $extension);
|
|
|
|
// Add the image to the volume CBZ
|
|
$cbz->addFromString($newFileName, $imageContent);
|
|
|
|
$imageCounter++;
|
|
}
|
|
|
|
$sourceCbz->close();
|
|
}
|
|
|
|
$cbz->close();
|
|
|
|
$response = new BinaryFileResponse($tempCbzPath);
|
|
$response->setContentDisposition(
|
|
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
|
|
$volumeName . '.cbz'
|
|
);
|
|
$response->headers->set('Content-Type', 'application/x-cbz');
|
|
|
|
// Clean up temp file after sending
|
|
$response->deleteFileAfterSend();
|
|
|
|
return $response;
|
|
}
|
|
|
|
private function isImageFile(string $fileName): bool
|
|
{
|
|
$imageExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'webp'];
|
|
$extension = strtolower(pathinfo($fileName, PATHINFO_EXTENSION));
|
|
|
|
return in_array($extension, $imageExtensions);
|
|
}
|
|
|
|
public function deleteCbzFile(string $filePath): bool
|
|
{
|
|
if (!$this->cbzExists($filePath)) {
|
|
return false;
|
|
}
|
|
|
|
return unlink($filePath);
|
|
}
|
|
|
|
public function cbzExists(string $filePath): bool
|
|
{
|
|
return file_exists($filePath) && is_readable($filePath);
|
|
}
|
|
}
|