diff --git a/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java b/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java index 9f1eb42..7d96455 100644 --- a/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java +++ b/api/src/main/java/fr/gameovergne/api/service/prestashop/PrestashopClient.java @@ -2,6 +2,7 @@ package fr.gameovergne.api.service.prestashop; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.io.ByteArrayResource; import org.springframework.http.*; import org.springframework.stereotype.Service; import org.springframework.util.LinkedMultiValueMap; @@ -233,74 +234,49 @@ public class PrestashopClient { * On envoie directement les bytes du fichier avec le bon content-type (image/jpeg, image/png, ...). */ - public ResponseEntity uploadProductImage(String productId, - String rawQuery, - MultipartFile imageFile) { + public ResponseEntity uploadProductImage( + String productId, + String rawQuery, + MultipartFile imageFile + ) { try { - // 1) URL complète vers Presta - StringBuilder urlBuilder = new StringBuilder(baseUrl) - .append("/images/products/") + // construction de l'URL relative (le RestClient a déjà baseUrl) + StringBuilder pathBuilder = new StringBuilder("/images/products/") .append(productId); - if (rawQuery != null && !rawQuery.isBlank()) { - urlBuilder.append("?").append(rawQuery); + pathBuilder.append('?').append(rawQuery); } - String url = urlBuilder.toString(); + String path = pathBuilder.toString(); byte[] bytes = imageFile.getBytes(); - // 2) Headers de la PART "image" - HttpHeaders partHeaders = new HttpHeaders(); - - MediaType mediaType = MediaType.APPLICATION_OCTET_STREAM; - if (imageFile.getContentType() != null && !imageFile.getContentType().isBlank()) { - try { - mediaType = MediaType.parseMediaType(imageFile.getContentType()); - } catch (Exception ignored) { - // on garde OCTET_STREAM - } - } - partHeaders.setContentType(mediaType); - - // Content-Disposition: form-data; name="image"; filename="xxx.jpg" - ContentDisposition disposition = ContentDisposition - .builder("form-data") - .name("image") - .filename(imageFile.getOriginalFilename()) - .build(); - partHeaders.setContentDisposition(disposition); - - // 3) Entity de la PART (équivalent ByteArrayContent en C#) - HttpEntity imagePart = new HttpEntity<>(bytes, partHeaders); - - // 4) Corps multipart : clé "image" - MultiValueMap body = new LinkedMultiValueMap<>(); - body.add("image", imagePart); - log.info("[PrestaShop] POST (image multipart) {} (size={} bytes, contentType={})", - url, bytes.length, mediaType); + baseUrl + path, bytes.length, imageFile.getContentType()); - // 5) Appel Presta via RestClient + // Ressource avec un filename pour que Spring pose bien le Content-Disposition + ByteArrayResource fileResource = new ByteArrayResource(bytes) { + @Override + public String getFilename() { + String name = imageFile.getOriginalFilename(); + return (name != null && !name.isBlank()) ? name : "image.jpg"; + } + }; + + // corps multipart : clé -> "image" + MultiValueMap body = new LinkedMultiValueMap<>(); + body.add("image", fileResource); + + // Envoi de la requête multipart/form-data return client.post() - .uri(url) + .uri(path) .contentType(MediaType.MULTIPART_FORM_DATA) .body(body) .retrieve() .toEntity(String.class); - } catch (HttpClientErrorException e) { - // on log ce que renvoie Presta et on renvoie tel quel au front - log.error("[PrestaShop] POST image error {} : {}", - e.getStatusCode().value(), e.getResponseBodyAsString()); - return ResponseEntity - .status(e.getStatusCode()) - .contentType(MediaType.APPLICATION_XML) - .body(e.getResponseBodyAsString()); } catch (IOException e) { log.error("[PrestaShop] Erreur lecture fichier image", e); - return ResponseEntity - .status(HttpStatus.INTERNAL_SERVER_ERROR) - .body("Erreur lecture image côté API"); + throw new RuntimeException("Erreur lors de la lecture du fichier image", e); } } } \ No newline at end of file