Un client proposant des fiches techniques au format PDF sur son site nous a signalé un comportement gênant : certains visiteurs, notamment sur mobile, voient le PDF s’ouvrir directement dans un lecteur intégré au navigateur plutôt que de le télécharger sur leur appareil. Pour un document destiné à être imprimé ou conservé hors ligne, ce n’est pas l’expérience souhaitée.
Ce comportement dépend en réalité du navigateur et de son type MIME associé, pas de WordPress lui-même. Un lien direct vers un fichier dans la médiathèque ne fait que pointer vers son URL statique, sur laquelle le serveur ne peut pas décider dynamiquement du comportement. La solution consiste à faire transiter le téléchargement par un script PHP qui envoie l’en-tête HTTP adéquat.
L’en-tête Content-Disposition
L’en-tête Content-Disposition: attachment indique explicitement au navigateur de proposer l’enregistrement du fichier plutôt que de tenter de l’afficher. C’est la même mécanique employée par de nombreux services d’export en ligne.
Créer un point de terminaison de téléchargement

Plutôt que de lier directement vers l’URL du fichier, on lie vers une route personnalisée qui se charge de servir le fichier avec les bons en-têtes. Voici une implémentation avec une règle de réécriture dédiée :
function ft_ajouter_regle_telechargement() {
add_rewrite_rule(
'^telecharger-fiche/([0-9]+)/?$',
'index.php?ft_telecharger_id=$matches[1]',
'top'
);
}
add_action( 'init', 'ft_ajouter_regle_telechargement' );
function ft_ajouter_variable_requete( $vars ) {
$vars[] = 'ft_telecharger_id';
return $vars;
}
add_filter( 'query_vars', 'ft_ajouter_variable_requete' );
function ft_servir_fichier_telechargement() {
$id = get_query_var( 'ft_telecharger_id' );
if ( ! $id ) {
return;
}
$chemin = get_attached_file( (int) $id );
if ( ! $chemin || ! file_exists( $chemin ) ) {
status_header( 404 );
exit;
}
$nom_fichier = basename( $chemin );
header( 'Content-Type: ' . mime_content_type( $chemin ) );
header( 'Content-Disposition: attachment; filename="' . $nom_fichier . '"' );
header( 'Content-Length: ' . filesize( $chemin ) );
readfile( $chemin );
exit;
}
add_action( 'template_redirect', 'ft_servir_fichier_telechargement' );
Après ajout de cette règle, un aller-retour sur la page « Permaliens » de l’administration reste nécessaire pour que la nouvelle route soit prise en compte par le système de réécriture d’URL.
Une alternative plus légère : l’attribut download
Pour un besoin simple, sans avoir à créer de route personnalisée, l’attribut HTML download sur le lien fonctionne dans la plupart des navigateurs récents :
<a href="https://exemple-client.fr/wp-content/uploads/2021/05/fiche-technique.pdf" download>Télécharger la fiche technique</a>
Cette solution a toutefois une limite connue : elle ne fonctionne fiablement que si le fichier est hébergé sur le même domaine que la page. Sur un CDN externe ou un sous-domaine dédié aux médias, certains navigateurs ignorent l’attribut et affichent le fichier normalement malgré tout.
Comparer les deux approches
| Critère | Attribut download | Script intermédiaire PHP |
|---|---|---|
| Simplicité de mise en œuvre | Immédiate | Nécessite une règle de réécriture |
| Fiabilité multi-domaines | Limitée | Totale |
| Contrôle des accès possible | Non | Oui, via current_user_can() |
| Journalisation des téléchargements | Non | Possible facilement |
Dès qu’un client demande à savoir combien de fois une fiche a été téléchargée, le script intermédiaire devient la seule option viable : c’est le bon moment pour y ajouter un compteur en meta de la pièce jointe.
En résumé
L’attribut download couvre les besoins simples et ponctuels, mais un script intermédiaire s’appuyant sur Content-Disposition reste la solution la plus robuste dès que le fichier provient d’un domaine différent ou que l’accès doit être contrôlé. Cette question est indépendante de l’organisation générale de la médiathèque, qui mérite un traitement à part entière.