Versions stable (inachevée mais prête à un déploiement en prod)
This commit is contained in:
226
src/main/java/dev/lions/components/FileUploadComponent.java
Normal file
226
src/main/java/dev/lions/components/FileUploadComponent.java
Normal file
@@ -0,0 +1,226 @@
|
||||
package dev.lions.components;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.annotation.PreDestroy;
|
||||
import jakarta.faces.application.FacesMessage;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.view.ViewScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.inject.Named;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import java.io.Serial;
|
||||
import lombok.Builder;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.primefaces.event.FileUploadEvent;
|
||||
import org.primefaces.model.file.UploadedFile;
|
||||
|
||||
import dev.lions.config.ApplicationConfig;
|
||||
import dev.lions.exceptions.FileUploadException;
|
||||
import dev.lions.services.FileStorageService;
|
||||
import dev.lions.utils.FileValidator;
|
||||
import dev.lions.utils.SecurityUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.UUID;
|
||||
|
||||
/**
|
||||
* Composant de gestion des téléchargements de fichiers.
|
||||
* Fournit une interface sécurisée et performante pour le téléchargement,
|
||||
* la validation et la gestion des fichiers dans l'application.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.1
|
||||
*/
|
||||
@Named
|
||||
@ViewScoped
|
||||
@Slf4j
|
||||
public class FileUploadComponent implements Serializable {
|
||||
|
||||
@Serial
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private static final int MAX_FILES = 10; // Limite de fichiers autorisés
|
||||
private static final String TEMP_DIR_PREFIX = "upload_"; // Préfixe pour répertoire temporaire
|
||||
|
||||
@Inject
|
||||
ApplicationConfig appConfig;
|
||||
|
||||
@Inject
|
||||
FileStorageService storageService;
|
||||
|
||||
@Inject
|
||||
FileValidator fileValidator;
|
||||
|
||||
@Inject
|
||||
SecurityUtils securityUtils;
|
||||
|
||||
@Getter
|
||||
private final List<UploadedFileInfo> uploadedFiles = new ArrayList<>();
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String uploadDirectory;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private boolean multiple = false;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private String acceptedTypes;
|
||||
|
||||
@Getter
|
||||
@Setter
|
||||
private long maxFileSize;
|
||||
|
||||
/**
|
||||
* Initialisation du composant.
|
||||
*/
|
||||
@PostConstruct
|
||||
public void init() {
|
||||
this.maxFileSize = appConfig.getMaxFileSize();
|
||||
this.acceptedTypes = appConfig.getAllowedFileTypes();
|
||||
this.uploadDirectory = createTempUploadDirectory();
|
||||
|
||||
log.info("Composant de téléchargement initialisé. Taille max: {}, Types acceptés: {}",
|
||||
maxFileSize, acceptedTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gère l'événement de téléchargement de fichier.
|
||||
*
|
||||
* @param event L'événement PrimeFaces contenant le fichier téléchargé.
|
||||
*/
|
||||
public void handleFileUpload(@NotNull FileUploadEvent event) {
|
||||
UploadedFile file = event.getFile();
|
||||
log.info("Téléchargement de fichier : {}", file.getFileName());
|
||||
|
||||
try {
|
||||
validateUploadRequest(file);
|
||||
UploadedFileInfo fileInfo = processUploadedFile(file);
|
||||
uploadedFiles.add(fileInfo);
|
||||
|
||||
addSuccessMessage("Fichier téléchargé avec succès : " + fileInfo.getFileName());
|
||||
} catch (FileUploadException e) {
|
||||
log.error("Erreur de validation du fichier : {}", file.getFileName(), e);
|
||||
addErrorMessage(e.getMessage());
|
||||
} catch (IOException e) {
|
||||
log.error("Erreur lors du traitement du fichier : {}", file.getFileName(), e);
|
||||
addErrorMessage("Une erreur est survenue lors du traitement du fichier.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la requête de téléchargement.
|
||||
*
|
||||
* @param file Le fichier téléchargé.
|
||||
*/
|
||||
private void validateUploadRequest(UploadedFile file) {
|
||||
if (uploadedFiles.size() >= MAX_FILES) {
|
||||
throw new FileUploadException("Vous avez atteint le nombre maximum de fichiers autorisés.");
|
||||
}
|
||||
fileValidator.validateFile(file, acceptedTypes, maxFileSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* Traite et stocke le fichier téléchargé.
|
||||
*
|
||||
* @param file Le fichier téléchargé.
|
||||
* @return Les informations du fichier.
|
||||
* @throws IOException En cas d'erreur de stockage.
|
||||
*/
|
||||
private UploadedFileInfo processUploadedFile(UploadedFile file) throws IOException {
|
||||
String secureFileName = generateSecureFileName(file.getFileName());
|
||||
Path destinationPath = storageService.storeFile(file.getInputStream(), uploadDirectory, secureFileName);
|
||||
|
||||
return UploadedFileInfo.builder()
|
||||
.id(UUID.randomUUID().toString())
|
||||
.fileName(file.getFileName())
|
||||
.contentType(file.getContentType())
|
||||
.size(file.getSize())
|
||||
.path(destinationPath)
|
||||
.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* Génère un nom de fichier sécurisé.
|
||||
*
|
||||
* @param originalFileName Nom original.
|
||||
* @return Nom sécurisé.
|
||||
*/
|
||||
private String generateSecureFileName(String originalFileName) {
|
||||
String extension = getFileExtension(originalFileName);
|
||||
return securityUtils.sanitizeFileName(UUID.randomUUID().toString() + "." + extension);
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'extension d'un fichier.
|
||||
*
|
||||
* @param fileName Nom du fichier.
|
||||
* @return Extension.
|
||||
*/
|
||||
private String getFileExtension(String fileName) {
|
||||
return fileName.substring(fileName.lastIndexOf('.') + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un répertoire temporaire pour les téléchargements.
|
||||
*
|
||||
* @return Le chemin du répertoire temporaire.
|
||||
*/
|
||||
private String createTempUploadDirectory() {
|
||||
return storageService.createTempDirectory(TEMP_DIR_PREFIX + UUID.randomUUID());
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les ressources lors de la destruction du composant.
|
||||
*/
|
||||
@PreDestroy
|
||||
public void cleanup() {
|
||||
try {
|
||||
storageService.deleteDirectory(uploadDirectory);
|
||||
log.info("Répertoire temporaire supprimé : {}", uploadDirectory);
|
||||
} catch (Exception e) {
|
||||
log.error("Erreur lors du nettoyage des ressources : {}", uploadDirectory, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un message de succès dans l'interface utilisateur.
|
||||
*
|
||||
* @param message Message à afficher.
|
||||
*/
|
||||
private void addSuccessMessage(String message) {
|
||||
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Succès", message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Ajoute un message d'erreur dans l'interface utilisateur.
|
||||
*
|
||||
* @param message Message à afficher.
|
||||
*/
|
||||
private void addErrorMessage(String message) {
|
||||
FacesContext.getCurrentInstance().addMessage(null, new FacesMessage(FacesMessage.SEVERITY_ERROR, "Erreur", message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Classe interne représentant un fichier téléchargé.
|
||||
*/
|
||||
@Getter
|
||||
@Builder
|
||||
public static class UploadedFileInfo {
|
||||
private final String id;
|
||||
private final String fileName;
|
||||
private final String contentType;
|
||||
private final long size;
|
||||
private final Path path;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user