- Ajout système complet de gestion des secteurs avec contours géographiques - Import des contours départementaux depuis GeoJSON - API REST pour la gestion des secteurs (/api/sectors) - Service de géolocalisation pour déterminer les secteurs - Migration base de données avec tables x_departements_contours et sectors_adresses - Interface Flutter pour visualisation et gestion des secteurs - Ajout thème sombre dans l'application - Corrections diverses et optimisations 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
12 KiB
Executable File
12 KiB
Executable File
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
- Upload → Validation du type MIME
- Analyse → Détection des dimensions originales
- Traitement → Redimensionnement si nécessaire
- Optimisation → Compression et résolution web
- Sauvegarde → Image optimisée + métadonnées
- 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
-
Upload d'avatar utilisateur
- Fichier JPG de 2MB
- Redimensionnement automatique à 250x250px
- Stockage dans
uploads/entites/5/users/123/
-
Document d'opération
- Fichier Excel de planning
- Stockage dans
uploads/entites/5/operations/2644/documents/ - Pas de traitement (fichier conservé tel quel)
-
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