feat: ajout de la fonctionnalité de conversion de fichiers CBR en CBZ, intégration d'un nouveau store pour gérer l'état de conversion, création de composants Vue pour l'upload de fichiers et le suivi de la progression, ainsi que la mise à jour de l'API pour gérer les conversions. Amélioration de la documentation API pour inclure les nouveaux endpoints et formats de fichiers supportés.

This commit is contained in:
ext.jeremy.guillot@maxicoffee.domains
2025-07-16 11:33:28 +02:00
parent 7a05934116
commit d9e78b5229
9 changed files with 1599 additions and 4 deletions

View File

@@ -0,0 +1,133 @@
export class ApiConversionRepository {
/**
* Convertit un fichier CBR/CBZ en CBZ
* @param {File} file - Le fichier à convertir
* @returns {Promise<Blob>} - Le fichier converti
*/
async convertFile(file) {
try {
// Validation du fichier
if (!file) {
throw new Error('Aucun fichier fourni');
}
// Validation de la taille (150MB max selon l'API)
const maxSize = 150 * 1024 * 1024; // 150MB en bytes
if (file.size > maxSize) {
throw new Error('Le fichier est trop volumineux (max 150MB)');
}
// Validation du type de fichier
const allowedTypes = ['.cbr', '.cbz'];
const fileName = file.name.toLowerCase();
const isValidType = allowedTypes.some(type => fileName.endsWith(type));
if (!isValidType) {
throw new Error('Type de fichier non supporté. Seuls les fichiers .cbr et .cbz sont acceptés');
}
// Création du FormData pour l'envoi multipart
const formData = new FormData();
formData.append('file', file);
// Appel à l'API
const response = await fetch('/api/conversions/convert', {
method: 'POST',
body: formData,
// On ne définit pas Content-Type pour laisser le navigateur gérer multipart/form-data
});
if (!response.ok) {
// Gestion des erreurs HTTP
let errorMessage = 'Erreur lors de la conversion';
try {
const errorData = await response.json();
errorMessage = errorData.message || errorData.detail || errorMessage;
} catch {
// Si la réponse n'est pas du JSON, on utilise le status text
errorMessage = response.statusText || errorMessage;
}
throw new Error(errorMessage);
}
// Récupération du fichier converti
const convertedFile = await response.blob();
// Vérification que le fichier n'est pas vide
if (convertedFile.size === 0) {
throw new Error('Le fichier converti est vide');
}
return convertedFile;
} catch (error) {
console.error('Erreur lors de la conversion:', error);
throw error;
}
}
/**
* Télécharge le fichier converti
* @param {Blob} fileBlob - Le fichier à télécharger
* @param {string} originalFileName - Nom original du fichier
*/
downloadConvertedFile(fileBlob, originalFileName) {
try {
// Génération du nom de fichier de sortie
const baseName = originalFileName.replace(/\.(cbr|cbz)$/i, '');
const outputFileName = `${baseName}.cbz`;
// Création d'un lien de téléchargement
const url = URL.createObjectURL(fileBlob);
const link = document.createElement('a');
link.href = url;
link.download = outputFileName;
// Déclenchement du téléchargement
document.body.appendChild(link);
link.click();
// Nettoyage
document.body.removeChild(link);
URL.revokeObjectURL(url);
} catch (error) {
console.error('Erreur lors du téléchargement:', error);
throw new Error('Impossible de télécharger le fichier converti');
}
}
/**
* Valide si un fichier peut être converti
* @param {File} file - Le fichier à valider
* @returns {Object} - Résultat de la validation {isValid: boolean, error?: string}
*/
validateFile(file) {
if (!file) {
return { isValid: false, error: 'Aucun fichier sélectionné' };
}
// Vérification de la taille
const maxSize = 150 * 1024 * 1024; // 150MB
if (file.size > maxSize) {
return {
isValid: false,
error: 'Le fichier est trop volumineux (maximum 150MB)'
};
}
// Vérification du type
const allowedTypes = ['.cbr', '.cbz'];
const fileName = file.name.toLowerCase();
const isValidType = allowedTypes.some(type => fileName.endsWith(type));
if (!isValidType) {
return {
isValid: false,
error: 'Type de fichier non supporté. Seuls les fichiers .cbr et .cbz sont acceptés'
};
}
return { isValid: true };
}
}