Thank you for your replies.
I tried creating a simple HTML file on my desktop:
<form method="post" action="http://127.0.0.1:8000/zip-folder/155">
<input type="submit">
</form>
This one downloads the file correctly, so it wouldn't be a token issue? By integrating this same code into my script, the file is generated but doesn't start the download.
I modified my script to better display the logs.
<?php
namespace App\Controller;
use Psr\Log\LoggerInterface;
use App\Entity\Product; // Utilise ton entité Product ici
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use ZipArchive;
use RecursiveIteratorIterator;
use RecursiveDirectoryIterator;
use FilesystemIterator;
class DownloadZipController extends AbstractController // N'oublie pas de déclarer ta classe héritant de AbstractController
{
#[Route('/zip-folder/{id}', name: 'zip_folder', methods: ['POST'])]
public function zipFolder(Product $entity, KernelInterface $kernel, LoggerInterface $logger): Response
{
$projectDir = $kernel->getProjectDir();
$sourceDir = $projectDir . '/public/download/' . $entity->getId();
$zipDir = $projectDir . '/var/zips/';
// Vérification de l'existence du répertoire source
if (!is_dir($sourceDir)) {
throw new \Exception("Dossier source introuvable: " . $sourceDir);
}
// Création du répertoire de destination si nécessaire
dump("Répertoire source : " . $sourceDir);
$logger->info("Répertoire source : " . $sourceDir);
if (!is_dir($zipDir)) {
mkdir($zipDir, 0777, true); // Vérifie les permissions
}
// Création du nom de fichier zip
$randomName = bin2hex(random_bytes(10)) . '.zip';
$zipPath = $zipDir . $randomName;
dump("Chemin du fichier ZIP : " . $zipPath);
$logger->info("Chemin du fichier ZIP : " . $zipPath);
// Création de l'archive zip
$zip = new ZipArchive();
if ($zip->open($zipPath, ZipArchive::CREATE) !== true) {
throw new \Exception("Impossible d'ouvrir le fichier zip");
}
// Parcours des fichiers à zipper
$files = new RecursiveIteratorIterator(
new RecursiveDirectoryIterator($sourceDir, FilesystemIterator::SKIP_DOTS),
RecursiveIteratorIterator::LEAVES_ONLY
);
foreach ($files as $file) {
$filePath = $file->getRealPath();
// Optionnellement, afficher les fichiers ajoutés
dump("Ajout du fichier : " . $filePath); // Vérifie chaque fichier ajouté
$relativePath = substr($filePath, strlen($sourceDir) + 1);
$zip->addFile($filePath, $relativePath);
}
// Fermeture de l'archive
$zip->close();
// Vérifie si le zip a bien été créé
dump("Zip créé avec succès : " . $zipPath);
// Générer un nom de fichier aléatoire pour le téléchargement
$downloadName = bin2hex(random_bytes(10)) . '.zip'; // Nom aléatoire pour le téléchargement
dump("Nom du fichier pour le téléchargement : " . $downloadName);
$logger->info("Nom du fichier pour le téléchargement : " . $downloadName);
// Retourne le fichier zip pour le téléchargement
// return $this->file($zipPath, $downloadName, ResponseHeaderBag::DISPOSITION_ATTACHMENT);
try {
$logger->info("Début du téléchargement du fichier : " . $zipPath);
return $this->file($zipPath, $downloadName, ResponseHeaderBag::DISPOSITION_ATTACHMENT);
} catch (\Exception $e) {
$logger->error("Échec du téléchargement du fichier : " . $zipPath . ". Erreur : " . $e->getMessage());
throw $e; // Relance l'exception pour que Symfony gère l'erreur
}
}
}
Here are the logs:
[2025-04-15T19:09:19.640675+02:00] request.INFO: Matched route "zip_folder". {"route":"zip_folder","route_parameters":{"_route":"zip_folder","_controller":"App\\Controller\\DownloadZipController::zipFolder","id":"155"},"request_uri":"http://127.0.0.1:8000/zip-folder/155","method":"POST"} []
[2025-04-15T19:09:19.648390+02:00] security.DEBUG: Checking for authenticator support. {"firewall_name":"main","authenticators":2} []
[2025-04-15T19:09:19.648430+02:00] security.DEBUG: Checking support on authenticator. {"firewall_name":"main","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator"} []
[2025-04-15T19:09:19.649218+02:00] security.DEBUG: Authenticator does not support the request. {"firewall_name":"main","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator"} []
[2025-04-15T19:09:19.649248+02:00] security.DEBUG: Checking support on authenticator. {"firewall_name":"main","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator"} []
[2025-04-15T19:09:19.649383+02:00] security.DEBUG: Authenticator does not support the request. {"firewall_name":"main","authenticator":"Symfony\\Component\\Security\\Http\\Authenticator\\Debug\\TraceableAuthenticator"} []
[2025-04-15T19:09:19.668764+02:00] doctrine.INFO: Connecting with parameters array{"use_savepoints":true,"driver":"pdo_mysql","idle_connection_ttl":600,"host":"127.0.0.1","port":3306,"user":"XXXX","password":null,"driverOptions":[],"defaultTableOptions":{"collation":"utf8mb4_unicode_ci"},"dbname":"XXXX","serverVersion":"10.4.32-MariaDB","charset":"utf8mb4"} {"params":{"use_savepoints":true,"driver":"pdo_mysql","idle_connection_ttl":600,"host":"127.0.0.1","port":3306,"user":"XXXX","password":null,"driverOptions":[],"defaultTableOptions":{"collation":"utf8mb4_unicode_ci"},"dbname":"XXXX","serverVersion":"10.4.32-MariaDB","charset":"utf8mb4"}} []
[2025-04-15T19:09:19.674579+02:00] doctrine.DEBUG: Executing statement: SELECT t0.id AS id_1, t0.name AS name_2, t0.slug AS slug_3, t0.priority AS priority_4, t0.masked AS masked_5 FROM category_shop t0 WHERE t0.masked = ? ORDER BY t0.priority ASC (parameters: array{"1":0}, types: array{"1":1}) {"sql":"SELECT t0.id AS id_1, t0.name AS name_2, t0.slug AS slug_3, t0.priority AS priority_4, t0.masked AS masked_5 FROM category_shop t0 WHERE t0.masked = ? ORDER BY t0.priority ASC","params":{"1":0},"types":{"1":1}} []
[2025-04-15T19:09:19.682093+02:00] doctrine.DEBUG: Executing statement: SELECT t0.id AS id_1, t0.title AS title_2, t0.slug AS slug_3, t0.content AS content_4, t0.online AS online_5, t0.subtitle AS subtitle_6, t0.price AS price_7, t0.created_at AS created_at_8, t0.updated_at AS updated_at_9, t0.attachment AS attachment_10, t0.category_id AS category_id_11, t0.fk_designer_id AS fk_designer_id_12 FROM product t0 WHERE t0.id = ? (parameters: array{"1":"155"}, types: array{"1":1}) {"sql":"SELECT t0.id AS id_1, t0.title AS title_2, t0.slug AS slug_3, t0.content AS content_4, t0.online AS online_5, t0.subtitle AS subtitle_6, t0.price AS price_7, t0.created_at AS created_at_8, t0.updated_at AS updated_at_9, t0.attachment AS attachment_10, t0.category_id AS category_id_11, t0.fk_designer_id AS fk_designer_id_12 FROM product t0 WHERE t0.id = ?","params":{"1":"155"},"types":{"1":1}} []
[2025-04-15T19:09:21.727992+02:00] app.INFO: Répertoire source : C:\xampp\htdocs\CultsV3/public/download/155 [] []
[2025-04-15T19:09:23.756200+02:00] app.INFO: Chemin du fichier ZIP : C:\xampp\htdocs\CultsV3/var/zips/922b28fc15001c3b5ca8.zip [] []
[2025-04-15T19:09:31.920133+02:00] app.INFO: Nom du fichier pour le téléchargement : 212cfb68d0739fc75668.zip [] []
[2025-04-15T19:09:31.920249+02:00] app.INFO: Début du téléchargement du fichier : C:\xampp\htdocs\CultsV3/var/zips/922b28fc15001c3b5ca8.zip [] []
[2025-04-15T19:09:31.943752+02:00] doctrine.INFO: Disconnecting [] []
Indeed, it may be easier to go through a link.