Mayan propose deux mécanismes distincts pour récupérer des documents : le téléchargement (servir le fichier natif, éventuellement en masse dans un ZIP) et l'export (générer un nouveau PDF à partir d'une version de document).
| Downloads | Exports | |
|---|---|---|
| Source | DocumentFile (fichier natif) |
DocumentVersion (pages rendues) |
| Format de sortie | Format natif + ZIP pour le bulk | PDF uniquement |
| Génération | Copie directe ou compression ZIP | Rendu page par page via Pillow |
| Opération rapide | Oui (téléchargement direct) | Non (tâche Celery asynchrone) |
| Résultat | Fichier natif (PDF, DOCX, image…) | PDF unifié de toutes les pages |
| Worker Celery | worker_c (queue documents_downloads) |
worker_c (queue documents_exports) |
| Permission | document_file_download |
document_version_export |
Télécharge le DocumentFile natif directement dans le navigateur, sans passer par une tâche Celery.
Via l'interface :
Document → Fichiers → [Fichier] → Téléchargement rapide
Via l'API REST :
curl -H "Authorization: Token <token>" \
-OJ \
"https://mayan.example.com/api/v4/documents/42/files/7/download/"
# → Retourne le fichier avec son MIME type et nom d'origine (HTTP 200)
Sélectionner plusieurs fichiers de plusieurs documents et les recevoir dans une archive ZIP. L'opération est asynchrone — Mayan génère le ZIP en arrière-plan et envoie une notification interne avec le lien de téléchargement.
Via l'interface :
task_document_file_compress mise en queueVia le shell Django :
from mayan.apps.document_downloads.classes import DocumentFileCompressor
from mayan.apps.documents.models import DocumentFile
files = DocumentFile.objects.filter(document__document_type__label='Factures')
compressor = DocumentFileCompressor(queryset=files)
compressor.compress_to_download_file(
organization_installation_url='https://mayan.example.com',
filename='factures_export.zip',
user=request.user
)
L'archive ZIP contient tous les fichiers sélectionnés avec leurs noms d'origine (str(document_file)). En cas de collision de noms, les fichiers sont renommés automatiquement.
Les messages de notification envoyés après génération d'un ZIP sont configurables :
| Paramètre | Défaut |
|---|---|
DOCUMENT_FILE_DOWNLOAD_MESSAGE_SUBJECT |
"Document files ready for download." |
DOCUMENT_FILE_DOWNLOAD_MESSAGE_BODY |
"The document files have been compressed and are available for download using the link: {{ download_url }} or from the downloads area ({{ download_list_url }})." |
Variables disponibles dans le gabarit : {{ download_url }}, {{ download_list_url }}, {{ document_list }}, {{ download_file }}.
# Configurer via variable d'environnement
MAYAN_DOCUMENT_FILE_DOWNLOAD_MESSAGE_SUBJECT="[Mayan] Vos fichiers sont prêts"
MAYAN_DOCUMENT_FILE_DOWNLOAD_MESSAGE_BODY="Téléchargez vos fichiers : {{ download_url }}"
L'export convertit toutes les pages d'une DocumentVersion en un fichier PDF unique. Chaque page est rendue en image (300 DPI) puis assemblée dans le PDF.
Via l'interface :
Document → Versions → [Version] → Exporter
→ Page de confirmation → Valider
→ Tâche Celery task_document_version_export mise en queue
→ Notification interne quand le PDF est prêt
Via l'API REST :
# Exporter une version (réponse 202 Accepted — asynchrone)
curl -X POST \
-H "Authorization: Token <token>" \
"https://mayan.example.com/api/v4/documents/42/versions/3/export/"
# → HTTP 202 Accepted
# Le PDF sera disponible dans la zone de téléchargements
Via le shell Django :
from mayan.apps.document_exports.classes import DocumentVersionExporter
from mayan.apps.documents.models import DocumentVersion
version = DocumentVersion.objects.get(pk=3)
exporter = DocumentVersionExporter(instance=version)
exporter.export_to_download_file(
organization_installation_url='https://mayan.example.com',
user=request.user
)
application/pdf){document_version}.pdfL'export utilise les pages de la
DocumentVersion, pas les pages duDocumentFileoriginal. Si la version a été remixée (pages réordonnées ou extraites de plusieurs fichiers), le PDF reflète cet ordre.
Les deux mécanismes (ZIP de téléchargement et PDF d'export) utilisent le même modèle DownloadFile de l'app storage.
1. Tâche Celery génère le fichier (ZIP ou PDF)
2. DownloadFile créé en base (user, filename, label, datetime)
3. Fichier écrit dans storage__downloadfile
→ par défaut : {MEDIA_ROOT}/download_files/
4. Notification interne envoyée à l'utilisateur avec le lien
5. Utilisateur accède à : Storage → Téléchargements
6. Fichier supprimé automatiquement après 2 jours (configurable)
Via l'interface :
Menu Storage → Fichiers à télécharger (ou icône de téléchargement)
Les fichiers générés y sont listés avec leur date de création et un lien de téléchargement direct.
Via l'API REST :
# Lister ses fichiers téléchargeables
curl -H "Authorization: Token <token>" \
"https://mayan.example.com/api/v4/storage/download_files/"
# Télécharger un DownloadFile spécifique
curl -H "Authorization: Token <token>" \
-OJ \
"https://mayan.example.com/api/v4/storage/download_files/5/download/"
| Paramètre | Défaut | Description |
|---|---|---|
STORAGE_DOWNLOAD_FILE_EXPIRATION_INTERVAL |
2 jours | Durée de conservation des fichiers générés |
Une tâche périodique s'exécute toutes les 10 minutes pour supprimer les DownloadFile expirés. L'utilisateur peut aussi supprimer manuellement depuis la liste de téléchargements.
# config.yml — augmenter la durée de rétention (en secondes)
STORAGE_DOWNLOAD_FILE_EXPIRATION_INTERVAL: 604800 # 7 jours
Worker : worker_c (nice=10, concurrence=4)
| Tâche | Queue | Paramètres | Description |
|---|---|---|---|
task_document_file_compress |
documents_downloads |
id_list, user_id, organization_installation_url |
Crée le ZIP de plusieurs DocumentFiles |
task_document_version_export |
documents_exports |
document_version_id, user_id, organization_installation_url |
Génère le PDF d'une DocumentVersion |
Les deux tâches sont asynchrones et fire-and-forget. L'utilisateur est notifié par message interne à la fin.
Le comportement du téléchargement direct est configurable via un backend.
mayan.apps.document_downloads.download_backends.http.DownloadBackendDocumentFileFileDirectStorage
Sert le fichier directement depuis le filesystem via Django. Adapté aux installations standard.
mayan.apps.document_downloads.download_backends.google.DownloadBackendDocumentFileGoogleCloudStorageSignedURL
Retourne une URL signée GCS au lieu de transférer le fichier via Django. Adapté quand les fichiers sont stockés dans un bucket GCS — le navigateur télécharge directement depuis GCS.
Configuration :
DOCUMENT_DOWNLOADS_DOCUMENT_FILE_DOWNLOAD_BACKEND: mayan.apps.document_downloads.download_backends.google.DownloadBackendDocumentFileGoogleCloudStorageSignedURL
DOCUMENT_DOWNLOADS_DOCUMENT_FILE_DOWNLOAD_BACKEND_ARGUMENTS:
expiration: 3600 # durée de validité de l'URL signée (secondes)
| Méthode | URL | Permission | Description |
|---|---|---|---|
GET |
/api/v4/documents/{id}/files/{fid}/download/ |
document_file_download |
Téléchargement direct d'un fichier |
POST |
/api/v4/documents/{id}/versions/{vid}/export/ |
document_version_export |
Lancer l'export PDF d'une version (202) |
GET |
/api/v4/storage/download_files/ |
— | Lister ses DownloadFiles |
GET |
/api/v4/storage/download_files/{id}/download/ |
— | Télécharger un DownloadFile |
DELETE |
/api/v4/storage/download_files/{id}/ |
— | Supprimer un DownloadFile |
| Permission | Namespace | Modèle | Description |
|---|---|---|---|
permission_document_file_download |
document_downloads |
DocumentFile |
Télécharger des fichiers documents |
permission_document_version_export |
document_exports |
DocumentVersion |
Exporter des versions en PDF |
| Événement | Namespace | Quand |
|---|---|---|
event_document_file_downloaded |
document_downloads |
Fichier téléchargé (direct ou bulk) |
event_document_version_exported |
document_exports |
Export PDF terminé |
event_download_file_created |
storage |
DownloadFile créé |
event_download_file_deleted |
storage |
DownloadFile supprimé (manuel ou expiration) |
docker compose logs worker_cdocuments_downloads est consommée{MEDIA_ROOT}/download_files/document_version.pages.count())docker compose logs worker_c | grep -i exportfrom mayan.apps.document_exports.classes import DocumentVersionExporter
from mayan.apps.documents.models import DocumentVersion
version = DocumentVersion.objects.get(pk=3)
exporter = DocumentVersionExporter(instance=version)
import io
buf = io.BytesIO()
exporter.export(file_object=buf)
print(f"PDF généré : {buf.tell()} octets")
Vérifier que la tâche périodique de nettoyage s'exécute. Elle est planifiée automatiquement via django_celery_beat. Si les fichiers ne sont pas supprimés après 2 jours, vérifier que le celery_beat est actif :
docker compose ps celery_beat
docker compose logs celery_beat | tail -20
| App | Fichier | Rôle |
|---|---|---|
document_downloads |
classes.py |
DocumentFileCompressor — création du ZIP |
document_downloads |
download_backends/http.py |
Backend HTTP direct |
document_downloads |
tasks.py |
task_document_file_compress |
document_downloads |
settings.py |
Gabarits de notification, backend |
document_exports |
classes.py |
DocumentVersionExporter — génération PDF |
document_exports |
tasks.py |
task_document_version_export |
storage |
models.py |
DownloadFile — modèle partagé |
storage |
views.py |
DownloadFileListView, DownloadFileDownloadView |