Intégration de MultipartFile dans les appels Feign avec Spring Cloud

Lors du développement d'une application Spring Cloud, une collègue a rencontré une erreur lors de l'utilisation de @FeignClient pour uploader des fichiers. Le paramètre en entrée était de type MultipartFile, ce qui a révélé une incompatibilité connue : Feign ne gère pas nativement les requêtes multipart/form-data. La résolution nécessite l'intégration de modules complémentaires, mais leur version doit correspondre à celle d'OpenFeign utilisée.

La documentation du projet feign-form précise les dépendances versionnées :

  • Les versions de feign-form antérieures à 3.5.0 fonctionnent avec OpenFeign 9.*.
  • À partir de feign-form 3.5.0, le module requiert OpenFeign 10.1.0 ou supérieur.
  • Aucune compatibilité ascendante n'est garantie pour feign-form au-delà de 3.5.0 avec OpenFeign inférieur à 10.*, en raison de refactorisations majeures dans OpenFeign 10.

En pratique, avec spring-cloud-openfeign, les versions antérieures à 2.0.3.RELEASE utilisent OpenFeign 9.*, tandis que les versions ultérieures optent pour OpenFeign 10.*. De plus, à partir de 2.0.3.RELEASE, spring-cloud-openfeign inclut déjà les dépendances feign-form adaptées, éliminant ainsi la nécessité de les spécifier manuellement. Notez que spring-cloud-starter-feign est obsolète et reste lié à OpenFeign 9.*.

Pour un projet utilisant Spring Cloud Greenwich.RELEACE, aucune dépendance supplémentaire n'est requise car le starter inclus gère les fichiers MultipartFile. Voici une implémentation type :

Configuration du client Feign

Créez une classe de configuration pour personnaliser l'encodeur Feign, en utilisant SpringFormEncoder pour supporter les formulaires multipart :

@Configuration
public class FeignMultipartConfig {

    @Autowired
    private ObjectFactory<HttpMessageConverters> messageConverterFactory;

    @Bean
    @Primary
    @Scope("prototype")
    public Encoder formEncoder() {
        return new SpringFormEncoder(new SpringEncoder(messageConverterFactory));
    }
}

Définition de l'interface Feign

Dans l'interface Feign, annotez les paramètres avec @RequestPart au lieu de @RequestParam, et spécifiez le type de consommation MEDIA_TYPE_MULTIPART :

@FeignClient(name = "file-service", configuration = FeignMultipartConfig.class)
public interface FileClient {

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    String uploadFile(@RequestPart("file") MultipartFile file, @RequestParam("label") String label);
}

Côté fournisseur de service

Le contrôleur côté serveur doit également utiliser @RequestPart pour le fichier et définir le type de contenu :

@RestController
public class FileServerController {

    @PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
    public String handleFileUpload(@RequestPart("file") MultipartFile uploadedFile, @RequestParam("label") String fileLabel) {
        if (!uploadedFile.isEmpty()) {
            try {
                Path storagePath = Paths.get(System.getProperty("java.io.tmpdir"), uploadedFile.getOriginalFilename());
                uploadedFile.transferTo(storagePath.toFile());
                return uploadedFile.getOriginalFilename();
            } catch (IOException e) {
                throw new RuntimeException("Échec du stockage du fichier", e);
            }
        }
        return "Aucun fichier fourni";
    }
}

Consommation depuis un autre service

Un contrôleur client peut invoquer le service Feign de manière classique, en transmettant directement le MultipartFile reçu :

@RestController
public class ProxyController {

    @Autowired
    private FileClient fileClient;

    @PostMapping("/proxy-upload")
    public String proxyUpload(@RequestPart("file") MultipartFile file, @RequestParam("label") String label) {
        return fileClient.uploadFile(file, label);
    }
}

Cette configuration assure le bon fonctionnement des uploads via Feign dans un environnement Spring Cloud, à condition de respecter les alignements de versions entre OpenFeign et les modules form.

Étiquettes: Feign spring-cloud MultipartFile spring-boot OpenFeign

Publié le 7 juillet à 01h59