J'essaie de télécharger un fichier lorsqu'un utilisateur clique sur le lien de téléchargement.
Dans le contrôleur:
$response = new Response();
$response->headers->set('Content-type', 'application/octect-stream');
$response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
$response->headers->set('Content-Length', filesize($filename));
return $response;
Ceci ouvre la boîte de dialogue pour enregistrer le fichier, mais indique que le fichier a une taille de 0 octet. Et le changer pour:
$response = new Response();
$response->headers->set('Content-type', 'application/octect-stream');
$response->headers->set('Content-Disposition', sprintf('attachment; filename="%s"', $filename));
$response->headers->set('Content-Length', filesize($filename));
$response->headers->set('Content-Transfer-Encoding', 'binary');
$response->setContent(readfile($filename));
return $response;
Je reçois un tas de caractères étranges au lieu de la boîte de dialogue de téléchargement de fichier.
Enfin, basculez la ligne "setContent" sur:
$response->setContent(file_get_contents($filename));
Il retourne une erreur PHP:
Erreur fatale: taille de mémoire autorisée ...
Des indices sur comment y parvenir? Je l'ai déjà fait auparavant dans PHP (sans MVC), mais je ne sais pas ce qui peut manquer pour le faire via Symfony2 ...
Peut-être que la solution consiste à définir memory_limit dans PHP.INI, mais je suppose que ce n’est pas la meilleure pratique ...
Tout d’abord, merci à tous pour vos réponses. J'ai finalement résolu ceci sans X-SendFile (ce qui est probablement la meilleure pratique). Quoi qu'il en soit, pour ceux qui ne peuvent pas utiliser le module Apache X-Sendfile (hébergement partagé), voici une solution:
// Generate response
$response = new Response();
// Set headers
$response->headers->set('Cache-Control', 'private');
$response->headers->set('Content-type', mime_content_type($filename));
$response->headers->set('Content-Disposition', 'attachment; filename="' . basename($filename) . '";');
$response->headers->set('Content-length', filesize($filename));
// Send headers before outputting anything
$response->sendHeaders();
$response->setContent(file_get_contents($filename));
return $response;
J'espère que cela t'aides!
La solution la plus confortable est
use Symfony\Component\HttpFoundation\BinaryFileResponse;
use Symfony\Component\HttpFoundation\ResponseHeaderBag;
$response = new BinaryFileResponse($file);
$response->setContentDisposition(ResponseHeaderBag::DISPOSITION_ATTACHMENT);
return $response;
Vous ne devez pas utiliser PHP pour télécharger des fichiers car il s’agit d’une tâche destinée à un serveur Apache ou Nginx. La meilleure option est d’utiliser X-Accel-Redirect (dans le cas de Nginx)/X-Sendfile ( dans le cas d’Apache) en-têtes pour le téléchargement de fichiers.
L'extrait d'action suivant peut être utilisé avec Nginx configuré pour télécharger des fichiers à partir de Symfony2:
return new Response('', 200, array('X-Accel-Redirect' => $filename));
PD1: Code pour Apache avec mod_xsendfile configuré:
return new Response('', 200, array(
'X-Sendfile' => $filename,
'Content-type' => 'application/octet-stream',
'Content-Disposition' => sprintf('attachment; filename="%s"', $filename))
);
Je ne sais pas si ça peut aider mais c'est application/octet-stream
ne pas application/octect-stream
Depuis Symfony 3.2, vous pouvez utiliser l’assistant du contrôleur file () , qui est un raccourci pour créer un BinaryFileResponse
comme mentionné dans une réponse précédente:
public function fileAction()
{
// send the file contents and force the browser to download it
return $this->file('/path/to/some_file.pdf');
}
+1 pour la réponse d'Alexandre.
Mais si vous ne pouvez pas utiliser X-Sendfile, vous devez utiliser le BinaryFileResponse ajouté dans la version 2.2: http://symfony.com/doc/current/components/http_foundation/introduction.html#serving-files =
Dans mon projet, le résultat est
$response = new \Symfony\Component\HttpFoundation\BinaryFileResponse($dir .DIRECTORY_SEPARATOR. $zipName);
$d = $response->headers->makeDisposition(
ResponseHeaderBag::DISPOSITION_ATTACHMENT,
$zipName
);
$response->headers->set('Content-Disposition', $d);
return $response;
Pour ceux qui n'ont pas la possibilité de définir des en-têtes:
L'attribut download
peut être utile selon les navigateurs à prendre en charge:
<a href="{file url}" download>
ou
<a href="{file url}" download="{a different file name}">
Ceci n'est pas supporté par tous les navigateurs existants. Voir cette page pour le support du navigateur: