Une des problématique récurrente dans le développement web, est sans doute cette grande question du téléchargement des pièces jointes.
Ici est la au travers du web l’on y découvre une montagne de snippets expliquant comment faire, forcer le téléchargement, modifier les headers, les réponses se suivents mais ne se ressemblent pas et les résultats sont toujours plus ou moins hasardeux.
Cependant grâce à Symfony nous disposons desormais d’un exemple fonctionnel et stable qui nous permettra de télécharger des pièces jointes avec aisance, le voici en images (façon de parler).
Voici le modèle « File » de l’exemple.
file:
columns:
filename: { type: string(1024) } // Nom original du fichier
url: { type: string(255) } // Nom sur le disque
mime: { type: string(255) } // Type
size: { type: integer(4) } // Taille
public function executeDownload(sfWebRequest $request)
{
$file = $this->getRoute()->getObject();
// On récupère notre objet de reponse.
$response = $this->getResponse();
// Nettoyage des headers pour être sur.
$response->clearHttpHeaders();
// Le type mime de notre objet (ici $file)
$response->setContentType($file->getMime());
$response->setHttpHeader('Pragma', 'public');
// Ici on assigne un nom "humainement lisible" à notre pièce jointe.
$response->setHttpHeader(
'Content-disposition',
'attachment; filename='.$file->getFilename()
);
$response->setHttpHeader(
'Content-length',
$file->getSize()
);
// Maintenant on envoi les Headers.
$response->sendHttpHeaders();
// On établi le contenu de notre fichier, en executant
// un readfile sur celui ci
$response->setContent(
readfile(sfConfig::get('sf_upload_dir').'/files/'.$file->getUrl())
);
// Et pour finir on envoi le contenu.
$response->sendContent();
// Ici on s'assure de ne retourner que les Headers pour eviter
// des caractères non voulus à la fin du fichier.
return sfView::HEADER_ONLY;
}
Le résultat est l’ouverture d’une fenêtre de téléchargement, et ce sous tous les navigateurs, fini les fichiers en text/plain affichés dans le navigateurs.
Dans mon exemple j’ai crée l’action « executeDownload » pour mon modèle « file », et pour récupérer un fichier j’utilise simple une url du type
http://www.myproject.sf/file/12/download
<a href="<?php echo url_for('file/download?id='.$file->getId()) ?>">
télécharger le fichier
</a>
En espérant que cet exemple vous servira
si vous avez des questions ou des améliorations à proposer n’hésitez pas.