浏览器窗口之间同步上传文件
对于 码头,我目前正在开发数字鼻子的应用程序。
这个应用程序需要上传BSEC配置文件--这是二进制数据。
一旦用户上传了文件,它就会通过MQTT发布,picockpit-client可以用它来配置BSEC AI算法来进行气体检测。
这里是部分网络界面的小预览。
在Vuetify中,有一个内置的GUI元素:v-file-input。
<v-file-input
v-model="bsecFile"
label="来自AI Studio的BSEC配置文件(.config)"
placeholder="在这里上传你的BSEC配置文件"
prepend-icon="mdi-paperclip"
概述
浓密的
显示尺寸
accept=".config"
@change="doUpload"
>
</v 文件输入
在这种情况下。 bsecFile 是我的模型。
注意:由于它是一个模型,它也可以被写到!
在MQTT上发布
这就是处理程序代码doUpload的样子(仍然包括调试信息)。
doUpload(){
console.log("model:")。
console.log(this.bsecFile)。
如果(this.bsecFile){
// 下面的代码不能可靠地工作,尽管它在理论上应该如此
// if (this.bsecFile.name.split(".")[1] != "config"){
// console.log("文件名不包括.config - 重置。")。
// this.bsecFile = null。
// }
// 否则 {
console.log("该变量似乎没有问题,正在尝试发布")。
var reader = new FileReader();
reader.addEventListener('load', (event) => {
console.log("文件读取成功!发布(现在用Uint8Array)。")。
// fn = 文件名, fs = 文件大小, fd = 文件(二进制)数据
const msg = {
fn:this.bsecFile.name。
fs: this.bsecFile.size。
fd: new Uint8Array (event.target.result)
}
console.log("消息是:")。
console.log(msg)。
this.$emit("bsec-upload-event", true)。
myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true)。
});
reader.readAsArrayBuffer(this.bsecFile)。
}
否则 {
console.log("该文件刚刚被清除,所以我们应该删除它......发送$nofile为true")。
const msg = {
"$nofile": true
}
console.log("消息是:")。
console.log(msg)。
this.$emit("bsec-upload-event", false)。
myMqtt.sendWBasePath(sensorSetBsecPath, msg, 1, true)。
}
}
请注意,我发布的信息包括二进制数据。
我为一个新的Uint8Array使用了一个构造函数,我把event.target.result--一个ArrayBuffer传给它。
这样一来,数据就会被准确地传递下去。
我们使用MsgPack将JavaScript对象打包成一个消息--它支持二进制数据。
在另一边,PiCockpit客户端接收二进制信息,并可以恢复一个(在这种情况下)Python对象,包括二进制数据。
让它在跨浏览器窗口的同步中发挥作用
第二个任务是在不同的浏览器窗口以及用户的会话中同步状态。
当用户返回时,我们希望将文件显示为已经上传给他们。
我想做的基本上是在JavaScript中建立一个新的文件对象实例,从我的Uint8Array中重新创建MQTT消息中的文件!
当然,我们订阅并监听MQTT消息。然后我们监测变量的变化,并修改模型bsecFile如下。
globalBsecFileWrapped(val){
// 如果我们不负责发送该信息,这将只被更新。
console.log("watch > globalBsecFileWrapped > contents:")。
console.log(this.globalBsecFileWrapped)。
console.log("我们现在要把它设置为一个文件......")。
如果(this.globalBsecFileWrapped.hasOwnProperty("$nofile")){
如果(this.globalBsecFileWrapped['$nofile']){
//将其更新为空--它是由不同的浏览器重置的。
this.bsecFile = null。
}
}
else if (this.globalBsecFileWrapped.hasOwnProperty("fd") && this.globalBsecFileWrapped.hasOwnProperty("fn") ) {
// 尝试 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。
// 调试
var reader = new FileReader();
reader.addEventListener('load', (event) => {
console.log("Debug >> File read successfully! publishing (now with Uint8Array).")。
// fn = 文件名, fs = 文件大小, fd = 文件(二进制)数据
const msg = {
fn:this.bsecFile.name。
fs: this.bsecFile.size。
fd: new Uint8Array (event.target.result)
}
console.log("消息是:")。
console.log(msg)。
});
reader.readAsArrayBuffer(this.bsecFile)。
}
}
注意这里的重要部分。
this.bsecFile = new Blob([this.globalBsecFileWrapped.fd], {type: "application/octet-stream"});
this.bsecFile.name = this.globalBsecFileWrapped.fn。
因此,为了重新创建文件(并让vuetify v-file-input更新为正确的文件(适当地显示大小和文件名),我们正在构建一个新的Blob。
重要提示:Blob的类型必须是 "application/octet-stream",否则将被解释为不同的类型,文件大小也将不再匹配。
最后,我们设置了新的名称--就这样了!"。