# Forcer le téléchargement plutôt que l’affichage de certains médias

> Un en-tête HTTP bien placé suffit pour que les PDF et fichiers ZIP proposés en médiathèque se téléchargent au lieu de s'ouvrir dans un nouvel onglet.

- Auteur : Clément Hadrot
- Publié le : 2021-05-18
- Mis à jour le : 2021-05-18
- Catégorie : Tips
- URL : https://wpmoderne.dev.wordpress-developpement.fr/tips/forcer-telechargement-plutot-affichage-medias/

## L’essentiel

- Content-Disposition force le téléchargement plutôt que l'affichage
- La solution passe par un script intermédiaire, pas par un lien direct
- Utile pour les PDF, ZIP et fichiers Office

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

> L'essentiel à retenir : Content-Disposition force le téléchargement plutôt que l'affichage ; La solution passe par un script intermédiaire, pas par un lien direct ; Utile pour les PDF, ZIP et fichiers Office

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.
