Implémentation du téléchargement d'images avec Vue.js et Spring Boot

Interface Utilisateur Vue.js

Voici le composant Vue.js pour gérer le téléchargement d'images en utilisant Element UI.

<el-row>
       <el-form-item label="Télécharger des fichiers" prop="fileList">
           <el-upload
               ref="uploader"
               action="#"
               list-type="picture-card"
               multiple
               accept="image/jpeg, image/jpg, image/png, application/vnd.openxmlformats-officedocument.wordprocessingml.document, application/pdf, application/msword"
               :file-list="fichiersSelectionnes"
               :auto-upload="false"
               :on-change="gestionChangementFichier"
               :on-remove="gestionSuppressionFichier"
               :on-preview="gestionApercuFichier"
           >
               <i slot="default" class="el-icon-plus"></i>
           </el-upload>
           <el-dialog :visible.sync="dialogApercuVisible">
               <img width="100%" :src="urlImageApercu" alt="">
           </el-dialog>
       </el-form-item>
   </el-row>

Logique de Validation des Fichiers

La fonction suivante gère la validation de la taille des fichiers et détecte les doublons avant le télécahrgement.

verifierTailleEtDoublons(contexte, fichier, listeFichiers) {
       const MAX_TAILLE_MB = 10;
       const tailleMo = fichier.size / 1024 / 1024;

       if (tailleMo > MAX_TAILLE_MB) {
           alert(`Le fichier ${fichier.name} dépasse la limite de ${MAX_TAILLE_MB} Mo.`);
           const index = contexte.fichiersSelectionnes.indexOf(fichier);
           if (index > -1) {
               contexte.fichiersSelectionnes.splice(index, 1);
           }
           contexte.fichiersSelectionnes = listeFichiers; // Met à jour l'état
           return;
       }

       const fichiersIdentiques = listeFichiers.filter(item => item.name === fichier.name);
       if (fichiersIdentiques.length > 1) {
           alert(`Le fichier ${fichier.name} existe déjà.`);
           const index = listeFichiers.indexOf(fichier);
           if (index > -1) {
               listeFichiers.splice(index, 1);
           }
       }
       contexte.fichiersSelectionnes = listeFichiers; // Met à jour l'état
   }

Méthodes Vue.js

Ces méthodes gèrent les événements de l'interface utilisateur, y compris le changement, la suppression et l'aperçu des fichiers.

gestionChangementFichier(fichier, listeFichiers) {
       this.verifierTailleEtDoublons(this, fichier, listeFichiers);
   },

   gestionSuppressionFichier(fichier, listeFichiers) {
       this.fichiersSelectionnes = listeFichiers;
       if (fichier.id) {
           this.$confirm('Êtes-vous sûr de vouloir supprimer ce fichier ? Cette action est irréversible.', 'Confirmation', {
               confirmButtonText: 'Oui',
               cancelButtonText: 'Non',
               type: 'warning'
           }).then(() => {
               supprimerFichierServeur(fichier.id).then(reponse => {
                   if (reponse.code === 200) {
                       alert(reponse.message);
                   } else {
                       // En cas d'échec, remet le fichier dans la liste
                       this.fichiersSelectionnes.push(fichier);
                       alert(reponse.message);
                   }
               });
           }).catch(() => {
               // En cas d'annulation, remet le fichier dans la liste
               this.fichiersSelectionnes.push(fichier);
           });
       }
   },

   gestionApercuFichier(fichier) {
       this.urlImageApercu = fichier.url;
       this.dialogApercuVisible = true;
   }

Sauvegarde des Données avec Fichiers

Cette méthode prépare et envoie les données du formulaire, y compris les fcihiers, au backend.

sauvegarderDonnees() {
       this.$refs["formulaire"].validate((estValide) => {
           if (estValide) {
               const donneesFormulaire = new FormData();
               this.fichiersSelectionnes.forEach(fichier => {
                   if (fichier.raw) { // S'assure que c'est un fichier brut
                       donneesFormulaire.append("fichiers", fichier.raw);
                   }
               });
               // Ajoute les autres champs du formulaire
               Object.keys(this.formulaire).forEach(cle => {
                   if (this.formulaire[cle] !== "") {
                       donneesFormulaire.append(cle, this.formulaire[cle]);
                   }
               });

               if (this.formulaire.id === "") {
                   ajouterEntree(donneesFormulaire).then(reponse => {
                       if (reponse.code === 200) {
                           alert(reponse.message);
                           this.actualiserListe();
                           this.afficherTableau = true;
                           this.afficherArbre = true;
                       } else {
                           alert(reponse.message);
                       }
                   });
               } else {
                   mettreAJourEntree(donneesFormulaire).then(reponse => {
                       if (reponse.code === 200) {
                           alert(reponse.message);
                           this.actualiserListe();
                           this.afficherTableau = true;
                           this.afficherArbre = true;
                       } else {
                           alert(reponse.message);
                       }
                   });
               }
               this.fichiersSelectionnes = []; // Réinitialise la liste des fichiers
           }
       });
   }

Interactions avec le Backend (API)

Définitions des appels d'API pour la gestion des fichiers.

// Récupération des fichiers liés à un élément
export function recupererFichiersElement(parametres) {
 return clientApi({
   url: 'api/sys-attach-filepath-info/query',
   method: 'get',
   parametres
 });
}

// Suppression d'un fichier spécifique
export function supprimerFichierServeur(id) {
 return clientApi({
   url: `api/sys-attach-filepath-info/${id}`,
   method: 'delete'
 });
}

// Ajout d'une nouvelle entrée avec fichiers
export function ajouterEntree(donnees) {
 return clientApi({
   url: 'api/sys-case-info/add',
   method: 'post',
   donnees
 });
}

// Mise à jour d'une entrée existante avec fichiers
export function mettreAJourEntree(donnees) {
 return clientApi({
   url: 'api/sys-case-info',
   method: 'put',
   donnees
 });
}

API Backend Spring Boot (Contrôleur)

Points d'entrée de l'API pour les opérations sur les fichiers et les entités.

@ApiOperation(value = "Récupérer des données paginées")
@ApiImplicitParams({
       @ApiImplicitParam(name = "pageIndex", value = "Numéro de page"),
       @ApiImplicitParam(name = "pageCount", value = "Nombre d'éléments par page"),
       @ApiImplicitParam(name = "relationId", value = "ID de l'entité associée")
})
@GetMapping(value = "/query")
public Response<String> findListByPage(@RequestParam(value = "page_index", required = false) Integer pageIndex,
                                      @RequestParam(value = "page_count") Integer pageCount,
                                      String relationId) {
   // Implémentation...
}

@ApiOperation(value = "Supprimer un fichier")
@DeleteMapping("{id}")
public Response<Integer> delete(@PathVariable("id") String id) {
   int result = sysAttachFilepathInfoService.delete(id);
   if (result > 0) {
       return new Response<>(ErrorCode.SUCESS_CODE, "Suppression réussie", result);
   } else {
       return new Response<>(ErrorCode.INTERNAL, "Échec de la suppression, erreur inconnue", null);
   }
}

@ApiOperation(value = "Ajouter une nouvelle entrée")
@PostMapping(value = "/add")
public Response<Integer> add(SysCaseInfo sysCaseInfo, @RequestParam("fichiers") MultipartFile[] files) {
   // Implémentation...
}

@ApiOperation(value = "Mettre à jour une entrée")
@PutMapping()
public Response<Integer> update(SysCaseInfo sysCaseInfo, @RequestParam("fichiers") MultipartFile[] files) {
   // Implémentation...
}

Implémentation Backend Spring Boot (Services)

Logique de gestion des fichiers et de persistance des données.

public static String telechargerFichier(MultipartFile[] fichiers, String id, String cheminBase, String nomTable) throws Exception {
   StringBuilder cheminsFichiers = new StringBuilder();
   if (fichiers != null && fichiers.length > 0) {
       File repertoireCible = new File(cheminBase + nomTable);
       if (!repertoireCible.exists()) {
           repertoireCible.mkdirs();
       }

       for (int i = 0; i < fichiers.length; i++) {
           String nomOriginal = fichiers[i].getOriginalFilename();
           String extension = nomOriginal.substring(nomOriginal.lastIndexOf("."));
           String nomFichierUnique = nomTable + "/" + id + "_" + System.currentTimeMillis() + extension;
           File fichierDestination = new File(cheminBase + nomFichierUnique);

           // Supprime le fichier existant s'il y en a un avant d'écrire
           if (fichierDestination.exists() && !fichierDestination.delete()) {
                throw new IOException("Erreur lors de la suppression du fichier existant : " + cheminBase + nomFichierUnique);
           }
           Path cheminDestination = Paths.get(cheminBase + nomFichierUnique);
           Files.write(cheminDestination, fichiers[i].getBytes());

           if (cheminsFichiers.length() > 0) {
               cheminsFichiers.append(",");
           }
           cheminsFichiers.append(nomFichierUnique);
       }
   }
   return cheminsFichiers.toString();
}

public void ajouterFichiersAssocies(MultipartFile[] fichiers, String idEntite, String nomTable) {
   List<SysAttachFilepathInfo> listeInfosFichiers = new ArrayList<>();
   if (fichiers != null && fichiers.length > 0) {
       String cheminServeurFichiers = fileConfig.getFileServer();
       try {
           String cheminsConcaténés = telechargerFichier(fichiers, idEntite, cheminServeurFichiers, nomTable);
           String[] cheminsIndividuels = cheminsConcaténés.split(",");
           for (String chemin : cheminsIndividuels) {
               SysAttachFilepathInfo info = new SysAttachFilepathInfo();
               info.setId(SnowIdUtil.getId()); // Génération d'ID unique
               info.setRelationId(idEntite);
               info.setRelationTable(nomTable);
               info.setFilePath(chemin);
               listeInfosFichiers.add(info);
           }
           if (!CollectionUtils.isEmpty(listeInfosFichiers)) {
               sysAttachFilepathInfoMapper.batchInsert(listeInfosFichiers);
           }
       } catch (IOException e) {
            // Gérer l'exception, par exemple logger ou lancer une exception personnalisée
            e.printStackTrace();
       } catch (Exception e) {
            // Gérer d'autres exceptions potentielles
            e.printStackTrace();
       }
   }
}

Configuration XML MyBatis

Instructions pour les opérations de base de données en masse.

<!-- Insertion groupée -->
<insert id="batchInsert" parameterType="com.hengan.involved.entity.SysAttachFilepathInfo">
   INSERT INTO sys_attach_filepath_info (id, relation_table, relation_id, file_path) values
   <foreach collection="list" item="item" separator=",">
       (#{item.id}, #{item.relationTable}, #{item.relationId}, #{item.filePath})
   </foreach>
</insert>

<!-- Mise à jour groupée (exemple simple) -->
<update id="batchUpdate" parameterType="java.util.List">
   <foreach collection="list" item="item" index="index" separator=";">
       UPDATE show_overview set item_num = #{item.itemNum} WHERE id=#{item.id}
   </foreach>
</update>

Étiquettes: Vue.js Element UI Spring Boot MyBatis téléchargement de fichiers

Publié le 26 juin à 04h43