Téléversement

Formats acceptés, limites de taille, validation de contenu, optimisation des images, nommage et service public des fichiers.

Un téléversement traverse cinq étapes : validation du fichier, optimisation de l'image, calcul du nom public, envoi au stockage objet, écriture de la fiche en base. Cette page décrit ce qui passe, ce qui est refusé, et ce que le fichier devient.

Deux voies y mènent, et elles partagent exactement ces cinq étapes : le formulaire de la médiathèque, qui passe par la route d'admin, et la façade uploadMedia du registre média, appelée depuis du code serveur. Tout ce qui suit vaut donc pour les deux. La seule différence est l'auteur : la route l'impose depuis la session, la façade le rend optionnel.

Formats et tailles acceptés

Le module ne demande pas au téléverseur de choisir un type. Il déduit le type du contenu depuis l'extension, puis applique le jeu de règles correspondant.

Contenu détectéExtensions acceptéesTaille maximale
Image.jpg, .jpeg, .png, .gif, .webp10 Mo
Tout le reste.pdf, .doc, .docx, .xls, .xlsx, .ppt, .pptx, .txt, .csv50 Mo

Il n'y a pas de troisième catégorie. Un fichier vidéo ou audio est donc systématiquement refusé, son extension n'appartenant à aucune des deux listes. L'interface propose pourtant des filtres Vidéo et Audio dans la médiathèque : ils ne servent qu'à filtrer d'éventuels médias hérités d'une version antérieure, jamais à en téléverser de nouveaux.

Le format .svg est toujours refusé, quelle que soit la liste applicable, parce qu'un SVG peut transporter du script exécutable.

Validation du contenu

La validation ne se contente pas de l'extension. Voir core/storage pour la fonction partagée.

  1. Extension contre la liste applicable.
  2. Taille contre la limite applicable.
  3. Signature binaire : les premiers octets du fichier doivent correspondre au format annoncé par l'extension. Une archive renommée en .png est arrêtée ici.
  4. Balayage de contenu : les premiers octets sont inspectés à la recherche de balises HTML, SVG, XML ou d'une ouverture de script. Cette couche attrape les fichiers polyglottes, valides dans deux formats à la fois.

Un échec de l'une de ces étapes annule le téléversement avant tout envoi au stockage.

Optimisation des images

Elle intervient après validation et avant envoi, uniquement sur les types image/jpeg, image/png, image/webp, image/avif et image/tiff.

Le GIF est volontairement exclu, pour préserver les animations.

Le traitement redimensionne l'image pour que son côté le plus long tienne dans LRVO_MODULE_MEDIAS_OPTIMIZE_MAX_DIMENSION, sans jamais l'agrandir, puis recompresse dans le même format. Un JPEG reste un JPEG, un PNG reste un PNG. Aucune conversion vers WebP n'est faite.

Deux garde-fous :

  • si le résultat n'est pas plus petit que l'original, l'original est conservé ;
  • si le traitement échoue, pour une image tronquée ou un format inattendu, l'original est conservé et le téléversement aboutit quand même. L'incident est journalisé.

Les métadonnées EXIF sont retirées par défaut. C'est ce qui supprime au passage la position GPS des photos prises au téléphone. Les conserver demande LRVO_MODULE_MEDIAS_OPTIMIZE_STRIP_METADATA=false, à faire en connaissance de cause.

Aucune vignette et aucune variante responsive ne sont générées. Un média correspond à un fichier et un seul. Le rendu responsive est du ressort de next/image, qui redimensionne à la demande depuis l'URL publique.

Les deux noms d'un fichier

Chaque média porte deux identifiants de fichier, qui ne servent pas à la même chose.

Clé de stockageNom public
Formemedia/<année>/<mois>/media_<horodatage>_<aléa>.<ext>Nom d'origine assaini
VisibleJamaisDans l'URL publique
ModifiableNonOui, depuis la fiche du média
UnicitéGarantie par l'aléaGarantie par suffixe numérique

La clé de stockage est fixée à la création et n'est jamais réécrite, pas même lors d'un remplacement de fichier. Le nom public, lui, se change librement.

C'est cette séparation qui permet de renommer un média sans casser quoi que ce soit : les contenus référencent l'identifiant du média, jamais son nom ni son URL. Voir Intégration.

Assainissement du nom public

Le nom d'origine est mis en minuscules, débarrassé de ses accents, ses soulignés deviennent des tirets, tout caractère hors [a-z0-9-] devient un tiret, les tirets consécutifs sont fusionnés et ceux des extrémités retirés. L'extension est conservée, en minuscules. Un nom entièrement composé de caractères écartés devient file.

En cas de collision avec un média existant, le module suffixe -2, puis -3, dans la limite de mille tentatives.

Un renommage manuel depuis la fiche est validé contre ^[a-z0-9-]+\.[a-z0-9]+$, sur 200 caractères au plus. L'extension n'est pas modifiable.

Ordre des écritures

Le fichier part au stockage avant l'écriture de la fiche en base. Si l'insertion échoue, l'objet fraîchement envoyé est supprimé pour ne pas laisser d'orphelin.

L'objet est envoyé avec un en-tête de cache d'un an, en immuable, ce qui est cohérent avec une clé de stockage jamais réécrite.

Service public du fichier

La route /lrvo/media/<nom public> retrouve la fiche par son nom, lit l'objet par sa clé de stockage, et diffuse le flux avec :

En-têteValeur
Content-TypeLe type MIME enregistré.
Cache-Controlprivate, max-age=3600
X-Content-Type-Optionsnosniff
X-Frame-OptionsDENY
Content-Dispositioninline pour JPEG, PNG, GIF et WebP. attachment pour tout le reste.

Un fichier non image est donc téléchargé plutôt qu'affiché, y compris un PDF. C'est une mesure de défense : un document affiché dans le contexte du site pourrait exécuter du script sur son origine.

La route n'exige ni session ni permission. Voir Configuration.

Remplacer un fichier

Le remplacement conserve l'identifiant, le nom public et toutes les références du média. Seuls la clé de stockage, le nom d'origine, le type MIME et la taille sont réécrits, et l'ancien objet est supprimé du stockage après coup.

Un changement de catégorie de contenu est refusé : on ne remplace pas une image par un document. La contrainte évite qu'un contenu qui affichait une image se retrouve à pointer un PDF.

Comme l'URL publique ne change pas, les caches intermédiaires peuvent continuer à servir l'ancien fichier. L'interface le signale au moment du remplacement.

Notes

  • Le module accepte indifféremment un fichier issu d'un formulaire ou un tampon binaire fourni par du code serveur, auquel cas le nom doit être passé explicitement.
  • L'auteur d'un média est facultatif. Un dépôt machine, par une tâche planifiée ou un import, laisse le champ nul et la médiathèque n'affiche alors aucun auteur. Seul un identifiant d'utilisateur réel est accepté par ailleurs, la colonne portant une clé étrangère vers la table des utilisateurs.
  • La médiathèque permet de télécharger jusqu'à cent médias d'un coup, dans une archive assemblée à la volée et sans recompression. Les objets manquants au stockage sont sautés, l'archive n'échoue pas pour autant.
  • Un média encore référencé par un contenu ne peut pas être supprimé. Le détacher d'abord. Voir Intégration.

Sur cette page