Sincronización de cargas de archivos entre ventanas del navegador

Para PiCockpitActualmente estoy desarrollando la aplicación Digital Nose.

Esta aplicación requiere una carga para el archivo de configuración BSEC, que son datos binarios.

Una vez que el usuario sube el archivo, se publica a través de MQTT, y picockpit-client puede utilizarlo para configurar el algoritmo BSEC AI para hacer la detección de gas.

Aquí tienes un pequeño avance de parte de la interfaz web:

imagen

Vuetify incluye un elemento de interfaz gráfica de usuario, v-file-input:

<fichero-v de entrada
     v-model="bsecFile"
     label="Archivo de configuración BSEC de AI Studio (.config)"
     placeholder="Cargue aquí su archivo de configuración BSEC"
     prepend-icon="mdi-paperclip"
     reseñado
     denso
     show-size
     accept=".config"
     @change="doUpload"
>
</v-file-input>

En este caso, bsecFile es mi modelo.

Nota: Como es un modelo, ¡también se puede escribir en él!

Publicación en MQTT

Así es como se ve el código del manejador doUpload (aún incluyendo la información de depuración):

    doUpload(){
         console.log("modelo:");
         console.log(this.bsecFile);
         if (this.bsecFile){
             // el código siguiente no funciona de forma fiable, aunque en teoría debería hacerlo
             // if (this.bsecFile.name.split(".")[1] != "config"){
             // console.log("El nombre del archivo no incluye .config - restableciendo");
             // this.bsecFile = null;
             // }
             // si no {
                 console.log("la variable parece estar bien, intentando publicar");
                 var reader = new FileReader();
                 reader.addEventListener('load', (event) => {
                     console.log("¡Fichero leído con éxito! publicando (ahora con Uint8Array)");
                     // fn = nombre del archivo, fs = tamaño del archivo, fd = datos del archivo (binario)
                     const msg = {
                           fn: this.bsecFile.name,
                           fs: this.bsecFile.size,
                           fd: new Uint8Array (event.target.result)
                     }
                     console.log("el mensaje es:");
                     console.log(msg);
                     this.$emit("bsec-upload-event", true);
                     myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true);                   
                 });
                 reader.readAsArrayBuffer(this.bsecFile);
         }
         si no {
             console.log("el archivo acaba de ser borrado, así que deberíamos eliminarlo... enviando $nofile como verdadero");
             const msg = {
                 "$nofile": true
             }
             console.log("el mensaje es:");
             console.log(msg);
             this.$emit("bsec-upload-event", false);
             myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true);
         }
     }

Tenga en cuenta que publico un mensaje que incluye datos binarios.

Utilizo un constructor para un nuevo Uint8Array al que paso event.target.result - un ArrayBuffer.

De este modo, los datos se transmiten tal cual.

Usamos MsgPack para empaquetar el objeto JavaScript en un mensaje - que soporta datos binarios.

Por otro lado, PiCockpit Client toma el mensaje binario, y puede reinstalar un objeto (en ese caso) Python, incluyendo los datos binarios.

Cómo hacer que funcione la sincronización entre ventanas del navegador

Una segunda tarea es sincronizar el estado entre diferentes ventanas del navegador y también sesiones del usuario.

Cuando el usuario regresa, queremos presentar el archivo como si ya se hubiera cargado.

¡Lo que quiero hacer es esencialmente construir una nueva instancia de Objeto Archivo en JavaScript, desde mi Uint8Array para recrear el archivo desde el mensaje MQTT!

Nos suscribimos y escuchamos el mensaje MQTT, por supuesto. Y luego monitoreamos la variable para los cambios, y modificamos el modelo bsecFile de la siguiente manera:

globalBsecFileWrapped(val){
     // esto sólo se actualizará si no fuimos responsables de enviar el mensaje en primer lugar.
     console.log("watch > globalBsecFileWrapped > contents:");
     console.log(this.globalBsecFileWrapped);
     console.log("vamos a establecer esto como un archivo ahora ...");
     if (this.globalBsecFileWrapped.hasOwnProperty("$nofile")){
         if (this.globalBsecFileWrapped['$nofile']){
             // actualízalo para que sea nulo - fue restablecido desde un navegador diferente.
             this.bsecFile = null;
         }
     }
     else if (this.globalBsecFileWrapped.hasOwnProperty("fd") && this.globalBsecFileWrapped.hasOwnProperty("fn")) {
         // intento 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;
         // depuración
             var reader = new FileReader();
             reader.addEventListener('load', (event) => {
                 console.log("Debug >> ¡Fichero leído con éxito! publicando (ahora con Uint8Array)");
                 // fn = nombre del archivo, fs = tamaño del archivo, fd = datos del archivo (binario)
                 const msg = {
                       fn: this.bsecFile.name,
                       fs: this.bsecFile.size,
                       fd: new Uint8Array (event.target.result)
                 }
                 console.log("el mensaje es:");
                 console.log(msg);
             });
             reader.readAsArrayBuffer(this.bsecFile);               
     }
}

anota las partes importantes aquí:

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

Así que, para recrear el archivo (y hacer que el vuetify v-file-input se actualice al archivo correcto (mostrando el tamaño adecuadamente, y el nombre del archivo) estamos construyendo un nuevo Blob.

Importante: el Blob debe tener el tipo "application/octet-stream", de lo contrario se interpretará como algo diferente y el tamaño de los archivos ya no coincidirá.

Y por último, fijamos el nuevo nombre: ¡ya está!

¿Quiere resolver problemas similares?

Estamos a su disposición para el alquiler