Synchronisation des téléchargements de fichiers entre les fenêtres du navigateur

Pour PiCockpitJe développe actuellement l'application Digital Nose.

Cette application nécessite un téléchargement pour le fichier de configuration du BSEC - qui est une donnée binaire.

Une fois que l'utilisateur a téléchargé le fichier, celui-ci est publié via MQTT, et picockpit-client peut l'utiliser pour configurer l'algorithme BSEC AI afin de détecter les gaz.

Voici un petit aperçu d'une partie de l'interface web :

Vuetify est livré avec un élément d'interface graphique intégré, v-file-input :

<v-file-input
     v-model="bsecFile"
     label="Fichier de configuration du BSEC à partir d'AI Studio (.config)".
     placeholder="Téléchargez votre fichier de configuration BSEC ici".
     prepend-icon="mdi-paperclip"
     décrit
     dense
     show-size
     accepter=".config"
     @change="doUpload"
>
</v-file-input>

Dans ce cas, bsecFile est mon modèle.

Note : Comme il s'agit d'un modèle, on peut aussi lui écrire !

Publication sur MQTT

Voici à quoi ressemble le code du gestionnaire doUpload (incluant toujours les informations de débogage) :

    doUpload(){
         console.log("modèle :") ;
         console.log(this.bsecFile) ;
         if (this.bsecFile){
             // le code ci-dessous ne fonctionne pas de manière fiable, bien qu'il devrait en théorie
             // si (this.bsecFile.name.split(".")[1] != "config"){
             // console.log("Le nom de fichier ne contient pas de .config - réinitialisation.") ;
             // this.bsecFile = null ;
             // }
             // else {
                 console.log("la variable semble être OK, j'essaie de publier") ;
                 var reader = new FileReader() ;
                 reader.addEventListener('load', (event) => {
                     console.log("Fichier lu avec succès ! publication (maintenant avec Uint8Array).") ;
                     // fn = nom du fichier, fs = taille du fichier, fd = données (binaires) du fichier
                     const msg = {
                           fn : ce.bsecFile.name,
                           fs : this.bsecFile.size,
                           fd : nouveau Uint8Array (event.target.result)
                     }
                     console.log("le message est :") ;
                     console.log(msg) ;
                     this.$emit("bsec-upload-event", true) ;
                     myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true) ;                   
                 });
                 reader.readAsArrayBuffer(this.bsecFile) ;
         }
         else {
             console.log("le fichier vient d'être effacé, nous devrions donc le supprimer ... en envoyant $nofile à true") ;
             const msg = {
                 "$nofile" : vrai
             }
             console.log("le message est :") ;
             console.log(msg) ;
             this.$emit("bsec-upload-event", false) ;
             myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true) ;
         }
     }

Notez que je publie un message qui comprend des données binaires.

J'utilise un constructeur pour un nouveau Uint8Array auquel je passe event.target.result - un ArrayBuffer.

De cette façon, les données sont transmises telles quelles.

Nous utilisons MsgPack pour emballer l'objet JavaScript dans un message - qui supporte les données binaires.

De l'autre côté, PiCockpit Client prend le message binaire, et peut réintégrer un objet Python (dans ce cas), y compris les données binaires.

Faire fonctionner la synchronisation entre les fenêtres du navigateur

Une deuxième tâche consiste à synchroniser l'état entre les différentes fenêtres du navigateur et les sessions de l'utilisateur.

Lorsque l'utilisateur revient, nous voudrions lui présenter le fichier comme ayant déjà été téléchargé.

Ce que je veux faire est essentiellement de construire une nouvelle instance de File Object en JavaScript, à partir de mon Uint8Array pour recréer le fichier à partir du message MQTT !

Nous nous abonnons et écoutons le message MQTT, bien sûr. Puis nous surveillons les changements de la variable, et modifions le modèle bsecFile comme suit :

globalBsecFileWrapped(val){
     // ceci ne sera mis à jour QUE si nous ne sommes pas responsables de l'envoi du message en premier lieu.
     console.log("watch > globalBsecFileWrapped > contents :") ;
     console.log(this.globalBsecFileWrapped) ;
     console.log("nous allons définir ceci comme un fichier maintenant ... ") ;
     if (this.globalBsecFileWrapped.hasOwnProperty("$nofile")){
         if (this.globalBsecFileWrapped['$nofile']){
             // mettez-le à jour pour qu'il soit nul - il a été réinitialisé à partir d'un autre navigateur.
             this.bsecFile = null ;
         }
     }
     else if (this.globalBsecFileWrapped.hasOwnProperty("fd") && this.globalBsecFileWrapped.hasOwnProperty("fn")) {
         // tentative 2
         // this.bsecFile = new File(this.globalBsecFileWrapped.fd, this.globalBsecFileWrapped.fn) ;
         this.bsecFile = new Blob([this.globalBsecFileWrapped.fd], {type : "application/octet-stream"}) ;
         this.bsecFile.name = this.globalBsecFileWrapped.fn ;
         // déboguer
             var reader = new FileReader() ;
             reader.addEventListener('load', (event) => {
                 console.log("Debug >> Fichier lu avec succès ! publication (maintenant avec Uint8Array).") ;
                 // fn = nom du fichier, fs = taille du fichier, fd = données (binaires) du fichier
                 const msg = {
                       fn : ce.bsecFile.name,
                       fs : this.bsecFile.size,
                       fd : nouveau Uint8Array (event.target.result)
                 }
                 console.log("le message est :") ;
                 console.log(msg) ;
             });
             reader.readAsArrayBuffer(this.bsecFile) ;               
     }
}

Notez les parties importantes ici :

this.bsecFile = new Blob([this.globalBsecFileWrapped.fd], {type : "application/octet-stream"}) ;
this.bsecFile.name = this.globalBsecFileWrapped.fn ;

Ainsi, pour recréer le fichier (et faire en sorte que l'entrée v-file de vuetify soit mise à jour vers le bon fichier (en indiquant la taille et le nom du fichier), nous construisons un nouveau Blob.

Important : le Blob doit avoir le type "application/octet-stream" - sinon il sera interprété comme quelque chose de différent et la taille des fichiers ne correspondra plus !

Et enfin, nous définissons le nouveau nom - c'est tout !

Vous cherchez à résoudre des problèmes similaires ?

Nous sommes disponibles pour la location