Files
geo/api/docs/README-UPLOAD.md

12 KiB

Système de Gestion des Fichiers - API Geosector

Vue d'ensemble

Ce document décrit l'organisation et la gestion des fichiers uploadés dans l'API Geosector. Le système permet de stocker et organiser différents types de fichiers par entité, utilisateur, opération et passage.

Structure des Dossiers

uploads/
├── entites/
│   ├── {entite_id}/
│   │   ├── documents/          # PDF, Excel généraux de l'entité
│   │   ├── images/            # Images de l'entité
│   │   ├── users/             # Dossier pour les fichiers des utilisateurs
│   │   │   └── {user_id}/     # Images par utilisateur (avatars, etc.)
│   │   └── operations/        # Dossier pour les opérations
│   │       └── {operation_id}/
│   │           ├── documents/ # Fichiers Excel de l'opération
│   │           └── passages/  # Fichiers des passages de cette opération
│   │               └── {passage_id}/ # PDF et images par passage
│   └── temp/                  # Fichiers temporaires avant validation

Exemples de chemins

  • Document d'entité : uploads/entites/5/documents/reglement_2024.pdf
  • Avatar utilisateur : uploads/entites/5/users/123/avatar.jpg
  • Excel d'opération : uploads/entites/5/operations/2644/documents/planning.xlsx
  • Photo de passage : uploads/entites/5/operations/2644/passages/789/photo_1.jpg

Structure de la Table medias

Table existante enrichie

-- Structure complète de la table medias
CREATE TABLE `medias` (
  `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
  `support` varchar(45) NOT NULL DEFAULT '' COMMENT 'Type de support (entite, user, operation, passage)',
  `support_id` int(10) unsigned NOT NULL DEFAULT 0 COMMENT 'ID de l\'élément associé',
  `fichier` varchar(250) NOT NULL DEFAULT '' COMMENT 'Nom du fichier stocké',
  `file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)',
  `file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets',
  `mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier',
  `original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé',
  `fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'entité propriétaire',
  `fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'opération (pour passages)',
  `file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier',
  `original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de l\'image',
  `original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de l\'image',
  `processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement',
  `processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement',
  `is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)',
  `description` varchar(100) NOT NULL DEFAULT '' COMMENT 'Description du fichier',
  `created_at` timestamp NOT NULL DEFAULT current_timestamp(),
  `fk_user_creat` int(10) unsigned NOT NULL DEFAULT 0,
  `updated_at` timestamp NULL DEFAULT NULL ON UPDATE current_timestamp(),
  `fk_user_modif` int(10) unsigned NOT NULL DEFAULT 0,
  PRIMARY KEY (`id`),
  UNIQUE KEY `id_UNIQUE` (`id`),
  KEY `idx_entite` (`fk_entite`),
  KEY `idx_operation` (`fk_operation`),
  KEY `idx_support_type` (`support`, `support_id`),
  KEY `idx_file_type` (`file_type`),
  CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
  CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;

Migration SQL pour table existante

-- Ajout des nouvelles colonnes à la table existante
ALTER TABLE `medias`
ADD COLUMN `file_type` varchar(50) DEFAULT NULL COMMENT 'Extension du fichier (pdf, jpg, xlsx, etc.)' AFTER `fichier`,
ADD COLUMN `file_size` int(10) unsigned DEFAULT NULL COMMENT 'Taille du fichier en octets' AFTER `file_type`,
ADD COLUMN `mime_type` varchar(100) DEFAULT NULL COMMENT 'Type MIME du fichier' AFTER `file_size`,
ADD COLUMN `original_name` varchar(255) DEFAULT NULL COMMENT 'Nom original du fichier uploadé' AFTER `mime_type`,
ADD COLUMN `fk_entite` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'entité propriétaire' AFTER `support_id`,
ADD COLUMN `fk_operation` int(10) unsigned DEFAULT NULL COMMENT 'ID de l\'opération (pour passages)' AFTER `fk_entite`,
ADD COLUMN `file_path` varchar(500) DEFAULT NULL COMMENT 'Chemin complet du fichier' AFTER `original_name`,
ADD COLUMN `original_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur originale de l\'image' AFTER `file_path`,
ADD COLUMN `original_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur originale de l\'image' AFTER `original_width`,
ADD COLUMN `processed_width` int(10) unsigned DEFAULT NULL COMMENT 'Largeur après traitement' AFTER `original_height`,
ADD COLUMN `processed_height` int(10) unsigned DEFAULT NULL COMMENT 'Hauteur après traitement' AFTER `processed_width`,
ADD COLUMN `is_processed` tinyint(1) unsigned DEFAULT 0 COMMENT 'Image redimensionnée (1) ou originale (0)' AFTER `processed_height`;

-- Ajout des index pour optimiser les requêtes
ALTER TABLE `medias`
ADD INDEX `idx_entite` (`fk_entite`),
ADD INDEX `idx_operation` (`fk_operation`),
ADD INDEX `idx_support_type` (`support`, `support_id`),
ADD INDEX `idx_file_type` (`file_type`);

-- Ajout des contraintes de clés étrangères
ALTER TABLE `medias`
ADD CONSTRAINT `fk_medias_entite` FOREIGN KEY (`fk_entite`) REFERENCES `entites` (`id`) ON UPDATE CASCADE ON DELETE CASCADE,
ADD CONSTRAINT `fk_medias_operation` FOREIGN KEY (`fk_operation`) REFERENCES `operations` (`id`) ON UPDATE CASCADE ON DELETE CASCADE;

Types de Support

1. Entité (support = 'entite')

  • Fichiers autorisés : PDF, Excel, Images (JPG, PNG)
  • Taille max : 20 MB
  • Usage : Documents généraux de l'entité (règlements, statuts, etc.)
  • Chemin : uploads/entites/{entite_id}/documents/

2. Utilisateur (support = 'user')

  • Fichiers autorisés : Images uniquement (JPG, PNG, GIF, WebP)
  • Taille max : 5 MB
  • Usage : Avatars, photos de profil
  • Chemin : uploads/entites/{entite_id}/users/{user_id}/
  • Traitement : Redimensionnement automatique

3. Opération (support = 'operation')

  • Fichiers autorisés : Excel uniquement (XLS, XLSX)
  • Taille max : 20 MB
  • Usage : Plannings, listes, données d'opération
  • Chemin : uploads/entites/{entite_id}/operations/{operation_id}/documents/

4. Passage (support = 'passage')

  • Fichiers autorisés : PDF et Images (JPG, PNG, PDF)
  • Taille max : 10 MB par fichier
  • Usage : Reçus, photos de passage, justificatifs
  • Chemin : uploads/entites/{entite_id}/operations/{operation_id}/passages/{passage_id}/
  • Traitement : Redimensionnement automatique pour les images

Traitement Automatique des Images

Règles de redimensionnement

  • Dimension maximale : 250px (hauteur ou largeur, selon la plus grande)
  • Résolution : 72 DPI (optimisé web)
  • Préservation du ratio : Redimensionnement proportionnel
  • Formats supportés : JPG, PNG, GIF, WebP
  • Qualité JPEG : 85% (bon compromis qualité/poids)

Exemples de transformation

Image originale 1000x800px → Image traitée 250x200px
Image originale 600x1200px → Image traitée 125x250px
Image originale 200x150px → Pas de redimensionnement (déjà < 250px)

Workflow de traitement

  1. Upload → Validation du type MIME
  2. Analyse → Détection des dimensions originales
  3. Traitement → Redimensionnement si nécessaire
  4. Optimisation → Compression et résolution web
  5. Sauvegarde → Image optimisée + métadonnées
  6. Nettoyage → Suppression du fichier temporaire

API Endpoints

Routes de gestion des fichiers

// Upload de fichiers
POST /api/medias/upload
Content-Type: multipart/form-data
Body: {
  "file": [fichier],
  "support": "entite|user|operation|passage",
  "support_id": 123,
  "description": "Description du fichier"
}

// Récupération d'un fichier
GET /api/medias/{id}

// Liste des fichiers par support
GET /api/medias/list/{support}/{support_id}

// Suppression d'un fichier
DELETE /api/medias/{id}

Exemples de requêtes

Upload d'un avatar utilisateur

curl -X POST "https://api.geosector.fr/medias/upload" \
  -H "Authorization: Bearer {token}" \
  -F "file=@avatar.jpg" \
  -F "support=user" \
  -F "support_id=123" \
  -F "description=Avatar utilisateur"

Upload d'une photo de passage

curl -X POST "https://api.geosector.fr/medias/upload" \
  -H "Authorization: Bearer {token}" \
  -F "file=@photo_passage.jpg" \
  -F "support=passage" \
  -F "support_id=789" \
  -F "description=Photo du passage"

Sécurité et Contrôles

Validation des fichiers

  • Types MIME : Vérification stricte du type de fichier
  • Extensions : Validation de l'extension par rapport au contenu
  • Taille : Limite selon le type de support
  • Contenu : Scan antivirus recommandé en production

Contrôles d'accès

  • Authentification : Token JWT requis
  • Autorisation : Utilisateur ne peut accéder qu'aux fichiers de son entité
  • Vérification : Contrôle que l'utilisateur appartient à l'entité du fichier
  • Logs : Traçabilité complète des uploads et accès

Nommage des fichiers

// Format : {timestamp}_{random}_{sanitized_name}.{extension}
// Exemple : 1640995200_a1b2c3_document_reglement.pdf

Gestion des Erreurs

Codes d'erreur HTTP

  • 400 : Fichier invalide ou paramètres manquants
  • 401 : Non authentifié
  • 403 : Accès refusé à cette entité
  • 413 : Fichier trop volumineux
  • 415 : Type de fichier non supporté
  • 500 : Erreur serveur lors du traitement

Messages d'erreur

{
  "status": "error",
  "message": "Type de fichier non autorisé pour ce support",
  "code": "INVALID_FILE_TYPE",
  "allowed_types": ["jpg", "png", "gif", "webp"]
}

Maintenance et Nettoyage

Nettoyage automatique

  • Fichiers temporaires : Suppression après 24h
  • Fichiers orphelins : Détection et suppression des fichiers sans référence en base
  • Anciennes opérations : Suppression en cascade lors de la suppression d'une opération

Commandes de maintenance

# Nettoyage des fichiers temporaires
php scripts/cleanup_temp_files.php

# Détection des fichiers orphelins
php scripts/find_orphan_files.php

# Statistiques d'utilisation
php scripts/storage_stats.php

Performances et Optimisation

Optimisations

  • CDN : Recommandé pour la distribution des fichiers
  • Cache : Headers de cache appropriés pour les fichiers statiques
  • Compression : Gzip pour les réponses API
  • Index : Index optimisés sur la table medias

Monitoring

  • Espace disque : Surveillance de l'utilisation
  • Performance : Temps de traitement des images
  • Erreurs : Logs des échecs d'upload et de traitement

Exemples d'Utilisation

Cas d'usage typiques

  1. Upload d'avatar utilisateur

    • Fichier JPG de 2MB
    • Redimensionnement automatique à 250x250px
    • Stockage dans uploads/entites/5/users/123/
  2. Document d'opération

    • Fichier Excel de planning
    • Stockage dans uploads/entites/5/operations/2644/documents/
    • Pas de traitement (fichier conservé tel quel)
  3. Photo de passage

    • Photo JPG de 8MB prise sur mobile
    • Redimensionnement automatique à 250px max
    • Stockage dans uploads/entites/5/operations/2644/passages/789/

Intégration frontend

// Upload avec progress
const uploadFile = async (file, support, supportId, description) => {
  const formData = new FormData();
  formData.append('file', file);
  formData.append('support', support);
  formData.append('support_id', supportId);
  formData.append('description', description);

  const response = await fetch('/api/medias/upload', {
    method: 'POST',
    headers: {
      Authorization: `Bearer ${token}`,
    },
    body: formData,
  });

  return response.json();
};

Version : 1.0
Date : Juin 2025
Auteur : API Geosector Team