Faciliter la planification
Quels outils pour planifier plus vite et mieux?

Cas concrets

Application web de gestion de ses photos personnelles

Solution full JS permettant d'uploader ses images, de les tagguer, de supprimer tous les doublons automatiquement et de retrouver les images suivant les tags

graphique en bar montrant le nombre d'images par année et la quantité tagguées et non tagguées

Contexte


Ce projet de Web App est né d'un besoin personnel d'avoir un lieu de stockage de nos photos familiales en un seul point et de répondre à quelques contraintes que nous rencontrions au quotidien dans cette gestion :


  • Eviter d'avoir des doublons d'images, voir même triplons, quadruplés etc. En effet, les photos que nous avons dans WhatsApp sont également souvent présentes dans notre galerie d'images. Si ma femme reçoit les mêmes images que moi dans son WhatsApp personnel, nous nous retrouverons alors avec 4 images identiques dans notre répertoire commun d'images ! Bien souvent, les noms des fichiers diffèrent entre nos 2 téléphones et donc il n'y a pas d'écrasement de ces fichiers qui sont pourtant identiques.


  • Eviter les écrasements d'images par erreur: comme les noms des images sont donnés par nos téléphones respectifs, il y a régulièrement des photos du téléphone de ma femme qui ont les mêmes noms que mes photos. Le problème c'est qu'il ne s'agit pas des mêmes photos. En effet, nos noms de fichiers d'images WhatsApp sont en général constitués de la date du jour et d'un numéro chrono. Si nous prenons des photos le même jour, nos images auront les mêmes noms, pour autant il ne s'agit pas des mêmes images. Lorsque nous les mettons dans le répertoire commun d'images, nous provoquons des écrasements par erreur.


  • Faciliter les recherches d'images dans notre banque d'images qui contient plusieurs milliers de fichiers. A ce jour, nos images étaient rangées dans des répertoires racines qui étaient nommés avec l'année. Mais à l'intérieur d'une année nous avions d'autres répertoires avec soit des noms de personnes, soit des noms de lieux (comme des lieux de vacances). Les recherches étaient très complexes ...


  • Il y a une dizaine d'année de cela nous avions utilisé le logiciel iphoto pour gérer nos images. Puis un jour nous avons laissé tomber Mac pour aller sur PC et nous avons récupéré nos images mais elles étaient rangées dans des répertoires imbriqués les uns dans les autres. Un enfer à gérer ensuite dans Windows, et je crois même que nous avons eu des pertes! Iphoto avait sa propre manière de gérer les images et sa méthode n'avait pas de sens pour un autre logiciel. Nous souhaitions donc nous libérer de la contrainte d'une application, dans le cas ou nous en changerions.


  • A noter que nous n'avons aucun besoin de retouches photos. Nous ne prenons pas le temps de faire ce travail, nous souhaitons simplement archiver et trier nos photos.



Etapes préalables


Etape 1: Mise en place d'un serveur


Nous avions un vieux Mac de 13 ans avec 4Go de Ram, autant vous dire que sa performance n'était plus au rendez-vous ! Plutôt que de se débarrasser de cette jolie bête, j'ai enlevé Mac OS et j'ai installé Ubuntu server. Une fois le serveur configuré, il m'a fallu paramétrer les clés SSH pour faciliter la communication entre ce Mac, mon PC Windows sur lequel je code et mon compte GitHub pour récupérer mes projets.


J'ai donc déployé mon application de gestion des images sur ce nouveau serveur.


Pour pouvoir ensuite y accéder depuis internet, je me suis rendu sur le paramétrage de ma box internet (LiveBox) et j'ai ouvert le port 3000 que je fais pointer sur le Mac. Je me retrouve donc avec un véritable serveur gratuit .... Il n'est pas très chargé en RAM mais cela m'oblige à produire un code de qualité :)


Paramétrage d'un port sur une livebox et pointage vers son serveur domestique


A noter qu'il y a une problématique d'adressage IP dynamique qui m'a obligé à utiliser les services d'un fournisseur nommé no-ip. Je bénéficie de leur service gratuitement mais je dois me connecter sur leur site 1 fois par mois, après avoir reçu une notification de leur part, afin de renouveler le fonctionnement pour le mois suivant. Le renouvellement est très simple et s'effectue en 10 secondes chrono.



Etape 2: Mise en place d'un proxy sur le serveur


La première problématique rencontrée est que je n'ai accès que au port 3000 depuis l'extérieur. Or j'ai le souhait de déployer plusieurs applications par la suite sur ce serveur. J'ai donc créé une application qui me sert de "portail". Cette application va tourner sur le port 3000 et aura 3 objectifs:


  • Réaliser une authentification: celle-ci sera réalisée à l'aide d'une session et non d'un token. En effet, nous aurons tout au plus 2 utilisateurs connectés en même temps avec pour seules données sauvegardées notre login et mot de passe. Il n'y aura donc pas de risque de surcharge de la RAM.


Ecran de connexion avec demande de login et mot de passe

  • Afficher un portail avec toutes les applications qui tournent sur le serveur (ici 3 applications pour le moment)


Portail applicatif permettant de se rendre sur toutes les applications en route sur le serveur domestique


  • Proxy applicatif: Router toutes les requêtes de ces applications par le port 3000 en les envoyant sur les ports correspondant aux applications. La mise en place du proxy a été réalisé à l'aide de la librairie http-proxy. Ce n'est pas simple de mettre en place ce type de module, car il y a une petite gymnastique au niveau des chemins utilisés pour consommer les API et renvoyer les fichiers statiques. Toutefois, une fois le mécanisme compris, la prise en main reste assez simple.



Workflow applicatif


Upload des images


Lors de cette étape, les images sont tout d'abord renommées à la volée par le programme qui "colle" un nombre à 3 chiffres aléatoires à la fin du nom du fichier original. Les images sont ensuite téléchargées dans la foulée côté serveur et mises dans un répertoire temporaire. Il n'y a plus d'écrasement de fichiers par erreur puisque des numéros aléatoires ont permis de créer des noms uniques.


A la suite de ce téléchargement dans le dossier temporaire, deux librairies ont été utilisées pour calculer l'empreinte de l'image en nombre binaire ! Cette empreinte binaire étant stockée dans la base de données, il est possible de vérifier pour chaque image si l'empreinte existe déjà en base de données. Si l'image existe déjà alors le fichier est purement supprimé du dossier temporaire. Si l'image n'est pas existante en base, alors le fichier est déplacé dans le répertoire final et l'empreinte binaire ajoutée dans une table de la BDD.


Le calcul de l'empreinte binaire à partir d'un buffer a été réalisé grâce aux librairies @canvas/image et blockhash-core.


Une gestion par websocket nous permet de bénéficier d'une barre de chargement en temps réel.


Deux options sont proposées au téléchargement :


  • Tagguer l'image avec l'année en cours : utile si les photos que vous téléchargez sont prises lors de l'année en cours
  • Enchainer avec le tag de toutes les photos téléchargées (voir partie suivante)




Barre de chargement gérée par l'utilisation de sockets io


Tagguer les images


Le principe des tags est de qualifier chaque image sur :

  • les personnes présentes sur l'image
  • l'année de prise de la photo
  • un évènement éventuel que l'on souhaite rattacher à la photo (ex: un mariage, un anniversaire ...)
  • le lieu de la prise de la photo


L'écran affiche l'image et tous les champs nécessaires pour créer/modifier/supprimer des tags en BDD et associer des tags à une image. Il est possible également de supprimer une image si on considère qu'elle ne présente pas d'intérêt particulier.


Un carrousel permet de circuler entre les photos afin d'enchainer rapidement d'une photo à l'autre.


D'un point de vue technique les photos sont simplement stockées dans un même répertoire sur le serveur. Si nous sommes plusieurs personnes à tagguer des images, il faut éviter de se retrouver sur les mêmes images en même temps. Il n'y a pas de verrou posé sur l'image puisque l'image en elle même n'est pas dans une BDD. Par conséquent, j'ai opté pour l'utilisation de sockets.

Dès qu'une personne se connecte, elle reçoit un socket et j'associe ce socket à l'image qu'elle est en train de tagguer. Ainsi, si une autre personne se connecte pour tagguer des images, le carrousel renverra pour image la première image ne contenant pas de socket. Si elle n'en contient pas, cela signifie que personne ne "travaille" dessus.


Ecran prévu pour tagguer une image avec pour exemple une photo de bébé


Recherches d'images et Téléchargement


L'avantage de tagguer les photos est de pouvoir effectuer des recherches sur toute la banque d'images selon les différents tags explicités ci-dessus. Un écran a donc été conçu pour effectuer la recherche avec tous les tags possibles. Pour préserver l'anonymat de mes proches, vous trouverez ci-dessous un exemple des photos dans lesquelles j'ai été tagguée :) Un survol de la souris sur une image permet de voir les différents tags posés sur la photo.


Si on souhaite télécharger des images sur notre poste en local, il est possible de cocher les images souhaitées et de cliquer sur "Télécharger".


Afin d'optimiser cette page, chaque petite carte est créé à la volée par le script front (vanilla js) au fur et à mesure du scroll afin d'éviter la création de 100% des éléments dans le DOM dès le départ. Il peut en effet y avoir beaucoup d'images sélectionnées, notamment lorsque l'on ne met pas de critères de recherche.

Pour aller plus loin dans l'optimisation, nous pourrions au téléchargement des images créer des duplications des photos en format miniature. On utiliserait ces images miniatures sur cette page de recherche pour accélérer le chargement. Je n'ai pas réalisé cette partie pour éviter de créer de nouvelles images sur le serveur et aussi parce que nous n'allons pas avoir une utilisation intensive de cet écran, en tout cas pour le moment.



Ecran de recherche d'images montrant la barre de recherche et les images renvoyées


Indicateur Global de suivi


Une page récapitulative permet de visualiser sous forme graphique le nombre de photos uploadées par année ainsi que le nombre de photos tagguées et non tagguées. Bien sûr nous pourrions rajouter toutes sortes d'autres indicateurs concernant les autres types de tags (personnes, lieux etc.) mais est-ce bien utile ? :)



graphique en bar montrant le nombre d'images par année et la quantité tagguées et non tagguées



Sauvegarde de la BDD et des images


Le fait de tagguer ses photos est tout de même un travail assez chronophage, surtout si on associe plusieurs Tags à une photo et si pas mal de personnes sont présentes sur la photo. Par conséquent, il serait regrettable de perdre tout ce travail. J'ai donc mis en place un child process pour faire un dump de la BDD et la récupérer sur une clé USB. Il y a également un child process qui lance un script de synchronisation des images présentes sur le serveur sur un répertoire d'un disque dur externe afin de redémarrer le projet même si le serveur crame !


Conclusion


J'espère que ce projet vous a intéressé ! Je serais curieux de savoir comment vous gérez la problématique des duplications d'images de votre côté, ainsi que votre méthode de recherche d'images ! N'hésitez pas à me contacter pour en discuter.


Vous pouvez retrouver le code du projet sur mon repo Github: projet imagesApp.


Ci-dessous vous pourrez avoir un rapide aperçu de la fin du chargement d'un batch d'images avec le tag d'une photo d'un enfant en vélo et de la fonction de recherche ensuite pour retrouver cette même photo :



Synthèse des principales fonctionnalités

  • Les images sont renommées en automatiques pour éviter les écrasements lorsque un même nom d'image existe dans son tel et celui de son conjoint alors qu'il ne s'agit pas de la même photo
  • Fonction de recherche par tag et année. Graphique récapitulatif du nombre d'images par année et du nombre d'images tagguées/non tagguées
  • Calcul des images en binaire et vérification qu'il n'y a aucun doublons (par exemple les images whatsapp sont parfois en doublons dans le téléphone de son conjoint ou de sa galerie)
  • Upload des images depuis ordinateur pour smartphone - Sauvegarde automatique dans un fichier synchronisé.
  • Création de nouveaux tags à la volée: Personne, Lieu et évènement. Plusieurs personnes peuvent tagguer en même temps sur le site sans conflit.
  • Téléchargement des images possibles pour les récupérer en local - sauvegarde automatique sur un disque externe
  • Technologies

    Postgres Express EJS Multer Express-session Child-process Google Charts Socket.io http-proxy @canvas/image blockhash-core

    Laisser un commentaire