fix: affichage des images via URLs signées Imago

- ImagoClient::get_thumbnail() utilise maintenant /thumbnail-url (URL signée)
- ImagoClient::get_file() utilise maintenant /download-url (URL signée)
- Fallback automatique thumbnail → fichier original si thumbnail indisponible
- Les images s'affichent dans la gallery même sans thumbnail généré
This commit is contained in:
2026-06-23 12:53:29 -04:00
parent a020cc3099
commit 8256d4c362
2 changed files with 50 additions and 8 deletions
+42 -7
View File
@@ -237,13 +237,33 @@ impl ImagoClient {
Ok(detail)
}
/// Récupère le thumbnail d'une image (raw bytes)
/// Récupère le thumbnail d'une image via URL signée
pub async fn get_thumbnail(&self, id: i64) -> Result<(Vec<u8>, String)> {
let response = self.client
.get(format!("{}/{}/thumbnail", self.images_base(), id))
// Étape 1 : obtenir l'URL signée
let sign_response: serde_json::Value = self.client
.get(format!("{}/{}/thumbnail-url", self.images_base(), id))
.header("X-API-Key", &self.api_key)
.send()
.await?
.error_for_status()?
.json()
.await?;
let signed_url = sign_response["url"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("URL signée manquante dans la réponse"))?;
// Si c'est un placeholder (pas de thumbnail), retourner une erreur propre
if signed_url.contains("placeholder") {
return Err(anyhow::anyhow!("Thumbnail non disponible (placeholder)"));
}
// Étape 2 : télécharger depuis l'URL signée
let full_url = format!("{}{}", self.base_url.trim_end_matches('/'), signed_url);
let response = self.client
.get(&full_url)
.send()
.await?
.error_for_status()?;
let content_type = response
@@ -257,20 +277,35 @@ impl ImagoClient {
Ok((data, content_type))
}
/// Récupère le fichier original (raw bytes)
/// Récupère le fichier original via URL signée
pub async fn get_file(&self, id: i64) -> Result<(Vec<u8>, String)> {
let response = self.client
.get(format!("{}/{}/file", self.images_base(), id))
// Étape 1 : obtenir l'URL signée
let sign_response: serde_json::Value = self.client
.get(format!("{}/{}/download-url", self.images_base(), id))
.header("X-API-Key", &self.api_key)
.send()
.await?
.error_for_status()?
.json()
.await?;
let signed_url = sign_response["url"]
.as_str()
.ok_or_else(|| anyhow::anyhow!("URL signée manquante dans la réponse"))?;
// Étape 2 : télécharger depuis l'URL signée
let full_url = format!("{}{}", self.base_url.trim_end_matches('/'), signed_url);
let response = self.client
.get(&full_url)
.send()
.await?
.error_for_status()?;
let content_type = response
.headers()
.get("content-type")
.and_then(|v| v.to_str().ok())
.unwrap_or("image/png")
.unwrap_or("application/octet-stream")
.to_string();
let data = response.bytes().await?.to_vec();
+8 -1
View File
@@ -420,7 +420,14 @@ async fn get_thumbnail(
let result = if full {
client.get_file(img_id).await
} else {
client.get_thumbnail(img_id).await
// Essayer le thumbnail d'abord, fallback vers le fichier original
match client.get_thumbnail(img_id).await {
Ok(t) => Ok(t),
Err(_) => {
tracing::info!("Thumbnail fallback -> fichier original pour id={}", id);
client.get_file(img_id).await
}
}
};
match result {