Refactor PrestashopClient to streamline image upload process and enhance error handling
This commit is contained in:
@@ -2,6 +2,7 @@ package fr.gameovergne.api.service.prestashop;
|
|||||||
|
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
import org.springframework.beans.factory.annotation.Value;
|
import org.springframework.beans.factory.annotation.Value;
|
||||||
|
import org.springframework.core.io.ByteArrayResource;
|
||||||
import org.springframework.http.*;
|
import org.springframework.http.*;
|
||||||
import org.springframework.stereotype.Service;
|
import org.springframework.stereotype.Service;
|
||||||
import org.springframework.util.LinkedMultiValueMap;
|
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, ...).
|
* On envoie directement les bytes du fichier avec le bon content-type (image/jpeg, image/png, ...).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public ResponseEntity<String> uploadProductImage(String productId,
|
public ResponseEntity<String> uploadProductImage(
|
||||||
|
String productId,
|
||||||
String rawQuery,
|
String rawQuery,
|
||||||
MultipartFile imageFile) {
|
MultipartFile imageFile
|
||||||
|
) {
|
||||||
try {
|
try {
|
||||||
// 1) URL complète vers Presta
|
// construction de l'URL relative (le RestClient a déjà baseUrl)
|
||||||
StringBuilder urlBuilder = new StringBuilder(baseUrl)
|
StringBuilder pathBuilder = new StringBuilder("/images/products/")
|
||||||
.append("/images/products/")
|
|
||||||
.append(productId);
|
.append(productId);
|
||||||
|
|
||||||
if (rawQuery != null && !rawQuery.isBlank()) {
|
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();
|
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<byte[]> imagePart = new HttpEntity<>(bytes, partHeaders);
|
|
||||||
|
|
||||||
// 4) Corps multipart : clé "image"
|
|
||||||
MultiValueMap<String, Object> body = new LinkedMultiValueMap<>();
|
|
||||||
body.add("image", imagePart);
|
|
||||||
|
|
||||||
log.info("[PrestaShop] POST (image multipart) {} (size={} bytes, contentType={})",
|
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<String, Object> body = new LinkedMultiValueMap<>();
|
||||||
|
body.add("image", fileResource);
|
||||||
|
|
||||||
|
// Envoi de la requête multipart/form-data
|
||||||
return client.post()
|
return client.post()
|
||||||
.uri(url)
|
.uri(path)
|
||||||
.contentType(MediaType.MULTIPART_FORM_DATA)
|
.contentType(MediaType.MULTIPART_FORM_DATA)
|
||||||
.body(body)
|
.body(body)
|
||||||
.retrieve()
|
.retrieve()
|
||||||
.toEntity(String.class);
|
.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) {
|
} catch (IOException e) {
|
||||||
log.error("[PrestaShop] Erreur lecture fichier image", e);
|
log.error("[PrestaShop] Erreur lecture fichier image", e);
|
||||||
return ResponseEntity
|
throw new RuntimeException("Erreur lors de la lecture du fichier image", e);
|
||||||
.status(HttpStatus.INTERNAL_SERVER_ERROR)
|
|
||||||
.body("<prestashop><errors><error><message>Erreur lecture image côté API</message></error></errors></prestashop>");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user