229 lines
8.8 KiB
Java
229 lines
8.8 KiB
Java
package com.olympus.hermione.services;
|
|
|
|
import org.springframework.stereotype.Service;
|
|
import java.io.File;
|
|
import java.io.IOException;
|
|
import java.nio.file.Files;
|
|
import java.nio.file.Path;
|
|
import java.nio.file.Paths;
|
|
import java.util.List;
|
|
|
|
import org.slf4j.Logger;
|
|
import org.slf4j.LoggerFactory;
|
|
import org.springframework.beans.factory.annotation.Value;
|
|
import org.springframework.core.io.FileSystemResource;
|
|
import org.springframework.core.io.Resource;
|
|
import org.springframework.http.HttpHeaders;
|
|
import org.springframework.http.HttpStatus;
|
|
import org.springframework.http.MediaType;
|
|
import org.springframework.http.ResponseEntity;
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
import com.olympus.hermione.dto.FileDeleteRequest;
|
|
|
|
@Service
|
|
public class FileService {
|
|
|
|
private Logger logger = LoggerFactory.getLogger(FileService.class);
|
|
|
|
@Value("${file.upload-dir}")
|
|
private String uploadDir;
|
|
|
|
public ResponseEntity<String> uploadFiles(String folderName, List<MultipartFile> files, String type) {
|
|
File folder = new File(uploadDir + folderName);
|
|
|
|
if (!folder.exists()) {
|
|
folder.mkdirs(); // Crea la cartella se non esiste
|
|
}
|
|
|
|
logger.info("path folder:", folder.getAbsolutePath().toString());
|
|
|
|
File emailFolder = new File(folder, "email");
|
|
|
|
if (!emailFolder.exists()) {
|
|
emailFolder.mkdirs();
|
|
}
|
|
|
|
try {
|
|
if (type.equals("PR")) {
|
|
for (MultipartFile file : files) {
|
|
String fileName = file.getOriginalFilename();
|
|
File destFile = new File(folder, fileName);
|
|
file.transferTo(destFile);
|
|
}
|
|
} else {
|
|
// Creazione delle sottocartelle "email" e "other" se non esistono
|
|
|
|
File otherFolder = new File(folder, "other");
|
|
|
|
|
|
for (MultipartFile file : files) {
|
|
String fileName = file.getOriginalFilename();
|
|
|
|
if (fileName != null && fileName.endsWith(".msg")) {
|
|
|
|
// Salva il file nella cartella "email"
|
|
File destFile = new File(emailFolder, fileName);
|
|
file.transferTo(destFile);
|
|
} else {
|
|
|
|
if (!otherFolder.exists()) {
|
|
otherFolder.mkdirs();
|
|
}
|
|
// Salva il file nella cartella "other"
|
|
File destFile = new File(otherFolder, fileName);
|
|
file.transferTo(destFile);
|
|
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
return ResponseEntity.ok(folderName);
|
|
|
|
} catch (Exception e) {
|
|
logger.error("Error uploading files: {}", e.getMessage());
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
.body("Error uploading files: " + e.getMessage());
|
|
}
|
|
}
|
|
|
|
|
|
public ResponseEntity<String> deleteFile(FileDeleteRequest request) {
|
|
String fileName = request.getFileName();
|
|
String folderPath = uploadDir + request.getFolderName();
|
|
|
|
File folder = new File(folderPath);
|
|
|
|
// Verifica che la directory esista
|
|
if (!folder.exists() || !folder.isDirectory()) {
|
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("Folder not found");
|
|
}
|
|
|
|
// Cerca il file nelle sottocartelle
|
|
File fileToDelete = findFileInSubdirectories(folder, fileName);
|
|
|
|
if (fileToDelete != null) {
|
|
if (fileToDelete.delete()) {
|
|
return ResponseEntity.ok("File deleted successfully");
|
|
} else {
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).body("Failed to delete file");
|
|
}
|
|
} else {
|
|
return ResponseEntity.status(HttpStatus.NOT_FOUND).body("File not found");
|
|
}
|
|
}
|
|
|
|
/**
|
|
* Metodo helper per cercare un file nelle sottocartelle.
|
|
*
|
|
* @param folder La directory di partenza
|
|
* @param fileName Il nome del file da cercare
|
|
* @return Il file trovato oppure null se non trovato
|
|
*/
|
|
private File findFileInSubdirectories(File folder, String fileName) {
|
|
File[] files = folder.listFiles();
|
|
|
|
if (files != null) {
|
|
for (File file : files) {
|
|
if (file.isDirectory()) {
|
|
// Ricorsione per cercare nelle sottocartelle
|
|
File found = findFileInSubdirectories(file, fileName);
|
|
if (found != null) {
|
|
return found;
|
|
}
|
|
} else if (file.getName().equals(fileName)) {
|
|
// File trovato
|
|
return file;
|
|
}
|
|
}
|
|
}
|
|
|
|
// File non trovato
|
|
return null;
|
|
}
|
|
|
|
/**
|
|
* Scarica un file dal path specificato
|
|
*
|
|
* @param filePath Il path relativo del file da scaricare
|
|
* @param executionId L'ID dell'esecuzione per il logging
|
|
* @return ResponseEntity con il file come Resource
|
|
*/
|
|
public ResponseEntity<Resource> downloadFile(String filePath, String executionId) {
|
|
try {
|
|
logger.info("Downloading file: {} for execution: {}", filePath, executionId);
|
|
|
|
// Normalizza il path rimuovendo eventuali separatori doppi o tripli
|
|
String normalizedPath = filePath.replaceAll("[\\\\/]+", "/");
|
|
|
|
// Check if path is absolute (starts with drive letter or uploadDir)
|
|
// If absolute, use it directly; otherwise, combine with uploadDir
|
|
Path file;
|
|
if (normalizedPath.matches("^[A-Za-z]:/.*") || normalizedPath.startsWith(uploadDir)) {
|
|
// Already absolute path - use directly (backward compatibility)
|
|
file = Paths.get(normalizedPath);
|
|
} else {
|
|
// Relative path - combine with uploadDir
|
|
file = Paths.get(uploadDir, normalizedPath);
|
|
}
|
|
|
|
logger.info("Upload directory: {}", uploadDir);
|
|
logger.info("Normalized relative path: {}", normalizedPath);
|
|
logger.info("Full file path: {}", file.toAbsolutePath());
|
|
|
|
// Verifica che il file esista e sia leggibile
|
|
if (!Files.exists(file)) {
|
|
logger.error("File not found: {}", file.toAbsolutePath());
|
|
return ResponseEntity.notFound().build();
|
|
}
|
|
|
|
if (!Files.isReadable(file)) {
|
|
logger.error("File not readable: {}", file.toAbsolutePath());
|
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
|
}
|
|
|
|
// Verifica che il file sia all'interno della directory di upload (security check)
|
|
Path uploadPath = Paths.get(uploadDir).toAbsolutePath().normalize();
|
|
Path filePath_abs = file.toAbsolutePath().normalize();
|
|
|
|
if (!filePath_abs.startsWith(uploadPath)) {
|
|
logger.error("Security violation: attempting to access file outside upload directory: {}", filePath_abs);
|
|
return ResponseEntity.status(HttpStatus.FORBIDDEN).build();
|
|
}
|
|
|
|
// Crea la risorsa file
|
|
Resource resource = new FileSystemResource(file);
|
|
|
|
// Determina il content type
|
|
String contentType = Files.probeContentType(file);
|
|
if (contentType == null) {
|
|
contentType = "application/octet-stream";
|
|
}
|
|
|
|
// Estrai il nome del file
|
|
String fileName = file.getFileName().toString();
|
|
|
|
// Costruisci gli header per il download
|
|
HttpHeaders headers = new HttpHeaders();
|
|
headers.add(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + fileName + "\"");
|
|
headers.add(HttpHeaders.CONTENT_TYPE, contentType);
|
|
headers.add(HttpHeaders.CONTENT_LENGTH, String.valueOf(resource.contentLength()));
|
|
|
|
logger.info("File downloaded successfully: {} (size: {} bytes)", fileName, resource.contentLength());
|
|
|
|
return ResponseEntity.ok()
|
|
.headers(headers)
|
|
.contentType(MediaType.parseMediaType(contentType))
|
|
.body(resource);
|
|
|
|
} catch (IOException e) {
|
|
logger.error("Error downloading file: {} - {}", filePath, e.getMessage(), e);
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
|
} catch (Exception e) {
|
|
logger.error("Unexpected error downloading file: {} - {}", filePath, e.getMessage(), e);
|
|
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR).build();
|
|
}
|
|
}
|
|
}
|