Sincronizzazione del caricamento dei file tra le finestre del browser

Per PiCockpitAttualmente sto sviluppando l'applicazione Digital Nose.

Questa applicazione richiede un upload per il file di configurazione BSEC - che è un dato binario.

Una volta che l'utente carica il file, questo viene pubblicato via MQTT, e picockpit-client può usarlo per configurare l'algoritmo BSEC AI per fare il rilevamento dei gas.

Ecco una piccola anteprima di una parte dell'interfaccia web:

immagine

Vuetify viene fornito con un elemento GUI incorporato, v-file-input:

<v-file-input
     v-model="bsecFile"
     label="File di configurazione BSEC da AI Studio (.config)"
     placeholder="Carica il tuo file di configurazione BSEC qui"
     prepend-icon="mdi-paperclip"
     delineato
     denso
     show-size
     accept=".config"
     @change="doUpload"
>
</v-file-input>

In questo caso, bsecFile è il mio modello.

Nota: poiché è un modello, può anche essere scritto!

Pubblicazione su MQTT

Ecco come appare il codice del gestore doUpload (che include ancora le informazioni di debug):

    doUpload(){
         console.log("modello:");
         console.log(this.bsecFile);
         se (this.bsecFile){
             // il codice qui sotto non funziona in modo affidabile, anche se in teoria dovrebbe
             // if (this.bsecFile.name.split(".")[1] != "config"){
             // console.log("Il nome del file non include .config - reset.");
             // this.bsecFile = null;
             // }
             // else {
                 console.log("la variabile sembra essere OK, provando a pubblicare");
                 var reader = nuovo FileReader();
                 reader.addEventListener('load', (event) => {
                     console.log("File letto con successo! pubblicazione (ora con Uint8Array)");
                     // fn = nome del file, fs = dimensione del file, fd = dati (binari) del file
                     const msg = {
                           fn: this.bsecFile.name,
                           fs: this.bsecFile.size,
                           fd: nuovo Uint8Array (event.target.result)
                     }
                     console.log("il messaggio è:");
                     console.log(msg);
                     this.$emit("bsec-upload-event", true);
                     myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true);                   
                 });
                 reader.readAsArrayBuffer(this.bsecFile);
         }
         else {
             console.log("il file è stato appena cancellato, quindi dovremmo rimuoverlo... inviando $nofile come true");
             const msg = {
                 "$nofile": vero
             }
             console.log("il messaggio è:");
             console.log(msg);
             this.$emit("bsec-upload-event", false);
             myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true);
         }
     }

Notate che pubblico un messaggio che include dati binari.

Uso un costruttore per un nuovo Uint8Array a cui passo event.target.result - un ArrayBuffer.

In questo modo, i dati vengono trasmessi esattamente come sono.

Usiamo MsgPack per impacchettare l'oggetto JavaScript in un messaggio - che supporta i dati binari.

Dall'altro lato, PiCockpit Client prende il messaggio binario, e può reintegrare un oggetto Python (in questo caso), compresi i dati binari.

Farlo funzionare per la sincronizzazione attraverso le finestre del browser

Un secondo compito è quello di sincronizzare lo stato attraverso diverse finestre del browser e anche sessioni dell'utente.

Quando l'utente ritorna, vorremmo presentare il file come se fosse già stato caricato.

Quello che voglio fare è essenzialmente costruire una nuova istanza dell'oggetto File in JavaScript, dal mio Uint8Array per ricreare il file dal messaggio MQTT!

Sottoscriviamo e ascoltiamo il messaggio MQTT, ovviamente. E poi monitoriamo la variabile per i cambiamenti, e modifichiamo il modello bsecFile come segue:

globalBsecFileWrapped(val){
     // questo sarà aggiornato solo se non siamo stati responsabili dell'invio del messaggio in primo luogo.
     console.log("watch > globalBsecFileWrapped > contents:");
     console.log(this.globalBsecFileWrapped);
     console.log("stiamo per impostare questo come un file ora ... ");
     se (this.globalBsecFileWrapped.hasOwnProperty("$nofile")){
         se (this.globalBsecFileWrapped['$nofile']){
             // aggiornalo per essere nullo - è stato resettato da un browser diverso.
             this.bsecFile = null;
         }
     }
     else if (this.globalBsecFileWrapped.hasOwnProperty("fd") && this.globalBsecFileWrapped.hasOwnProperty("fn")) {
         // tentativo 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;
         // debug
             var reader = nuovo FileReader();
             reader.addEventListener('load', (event) => {
                 console.log("Debug >> File letto con successo! pubblicazione (ora con Uint8Array)");
                 // fn = nome del file, fs = dimensione del file, fd = dati (binari) del file
                 const msg = {
                       fn: this.bsecFile.name,
                       fs: this.bsecFile.size,
                       fd: nuovo Uint8Array (event.target.result)
                 }
                 console.log("il messaggio è:");
                 console.log(msg);
             });
             reader.readAsArrayBuffer(this.bsecFile);               
     }
}

notare le parti importanti qui:

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

Quindi, per ricreare il file (e far sì che il vuetify v-file-input si aggiorni al file corretto (mostrando adeguatamente la dimensione e il nome del file) stiamo costruendo un nuovo Blob.

Importante: il Blob deve avere il tipo "application/octet-stream" - altrimenti sarà interpretato come qualcosa di diverso e il filesize non corrisponderà più!

E infine, impostiamo il nuovo nome - questo è tutto!

Cerchi di risolvere problemi simili?

Siamo disponibili per il noleggio