La gestion de l’upload de fichiers images dans Springboot s’appuie sur plusieurs classes et fichiers.
FileUploadController agit comme un contrôleur qui va recevoir la demande d’upload de fichier (via l’url /upload) et la demande d’afficher l’image ( via l’url /files/{filename:.+} ). nCette classe contient une référence sur une classe FileSystemStorageService implementant l’interface StorageService.
StorageService est une simple interface qui permet de définir les actions classiques d’un service Spring de stockage.
FileSystemStorageService implémente de façon réelle l’interface StorageService pour la gestion du lieu de stockage des fichiers. Par ailleurs, pour une raison de sécurité, on peut stocker les fichiers uploadés dans un dossier dont l’accès est protégé pour éviter l’upload de fichiers critiques sur le serveur en devinant l’URL.
upload.html est un fichier gérant le formulaire HTML permettant d’envoyer un fichier simplement sans javascript encore une fois pour simplifier cet exemple.
Après les liaisons entre les fichiers, voici le contenu très simplifié de ces derniers:
<!DOCTYPE html><html lang="en"><head> <title>upload</title> <body> <form method="post" enctype="multipart/form-data" action="/upload"> <div> <label for="file">Sélectionner le fichier à envoyer</label> <input type="file" id="file" name="file" > </div> <div> <button>Envoyer</button> </div> </form> </body></html>
L’upload d’un fichier image se fait vers le contrôleur FileUploadController via l’action /upload, cette classe permet aussi l’affichage d’une ressource image dans le navigateur (il manque la gestion des exceptions à coder en plus) :
@Controller public class FileUploadController { // Service spring de stockage des fichiers private final StorageService storageService; // Constructeur de la classe avec l'activation du service @Autowired public FileUploadController(StorageService storageService) { this.storageService = storageService; } @GetMapping("/files/{filename:.+}") @ResponseBody public ResponseEntity<Resource> serveFile(@PathVariable String filename) { Resource file = storageService.loadAsResource(filename); String mimeType = URLConnection.guessContentTypeFromName(file.getFilename()); long contentLength = 0; try { contentLength = file.contentLength(); } catch (IOException e) { } InputStream fileInputStream = null; try { fileInputStream = file.getInputStream(); } catch (IOException e) {} return ResponseEntity.ok().contentLength( contentLength ) .contentType(MediaType.parseMediaType( mimeType )) .body(new InputStreamResource( fileInputStream )); } //Upload d'un fichier @PostMapping("/upload") public String handleFileUpload(@RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) { storageService.store(file); return "redirect:/"; } }
L’interface StorageService permet de définir les méthodes à implémenter par FileSystemStorageService.
public interface StorageService { void init(); String store(MultipartFile file); Stream<Path> loadAll(); Path load(String filename); Resource loadAsResource(String filename); void deleteAll(); }
Enfin la classe FileSystemStorageService permet de créer un service qui va stocker les fichiers dans un dossier ./Stockage dans le projet Spring (la gestion des exceptions est à coder en plus):
@Service public class FileSystemStorageService implements StorageService { private final Path rootLocation; @Autowired public FileSystemStorageService() { this.rootLocation = Paths.get("./Stockage/"); } @Override @PostConstruct public void init() { try { Files.createDirectories(rootLocation); } catch (IOException e) {} } @Override public String store(MultipartFile file) { String filename = StringUtils.cleanPath(file.getOriginalFilename()); try { if (file.isEmpty()) {} if (filename.contains("..")) { } try (InputStream inputStream = file.getInputStream()) { Files.copy(inputStream, this.rootLocation.resolve(filename), StandardCopyOption.REPLACE_EXISTING); } } catch (IOException e) { } return filename; } @Override public Stream<Path> loadAll() { try { return Files.walk(this.rootLocation, 1).filter(path -> !path.equals(this.rootLocation)).map(this.rootLocation::relativize); } catch (IOException e) { return null; } } @Override public Path load(String filename) { return rootLocation.resolve(filename); } @Override public Resource loadAsResource(String filename) { Path file = load(filename); Resource resource = null; try { resource = new UrlResource(file.toUri()); if (resource.exists() || resource.isReadable()) { return resource; } else { System.out.println("File not found " + filename); } } catch (MalformedURLException e) { } return resource; } @Override public void deleteAll() { FileSystemUtils.deleteRecursively(rootLocation.toFile()); } }
Le code du contrôleur FileUploadController permet d’afficher le fichier image dans le navigateur, si on souhaite proposer en téléchargement un fichier, la méthode serveFile doit être modifiée:
Resource file = storageService.loadAsResource(filename);
return ResponseEntity.ok().header(HttpHeaders.CONTENT_DISPOSITION,
"attachment; filename=\"" + file.getFilename() + "\"").body(file);
Merci à cet article (https://spring.io/guides/gs/uploading-files/) qui a permit la rédaction de ce contenu.