nodejs二进制websocket mimetype处理
nodejs binary websocket mimetype handling
我不能100%确定,但从我通过websocket发送blob(二进制数据)时读取的内容来看,blob不包含任何文件信息。(此外,官方规范规定wesockets只发送原始二进制文件)
- 文件大小
- mimetype
- 用户信息(稍后解释)
我正在使用https://github.com/websockets/ws
测试:
直接从输入文件发送blob。
ws.send(this.files[0]) //this should already contain the info
使用本地javascript api从文件创建一个新的blob,设置正确的mimetype。
ws.send(new Blob([this.files[0]],{type:this.files[0].type})); //also this
在两侧,您都只能获得有效的blob,而没有任何其他信息。
是否可以附加一个4kb预定义的json数据,该数据也转换为二进制文件,其中包含mimetype和filesize等重要信息,然后在需要的时候把4kb分开
{"mime":"txt/plain","size":345}____________ 4KB_REST_OF_THE_BINARY
或
ws.send({"mime":"txt'/plain","size":345})
ws.send(this.files[0])
即使第一个是有史以来最糟糕的解决方案,它也允许我一次性发送所有内容。
第二个有一个大问题:
这是一个聊天,允许发送文件,如文件,图像,音乐视频。
在发送二进制数据之前,我可以在发送文件/用户信息时编写某种握手系统。
但是
如果另一个人也发送了一个文件,因为它是异步的,那么握手系统就没有机会确定哪个文件适合正确的用户和mimetype。
那么,如何在多用户异步环境中正确发送二进制文件呢
我知道我可以转换到base64,但那要大30%。
顺便说一句。对苹果感到非常失望。。。虽然chrome可以正确显示每个二进制数据,但我的ios设备无法处理blob,只有图像会以blob或base64格式显示,甚至不是一个简单的txt文件。基本上只有<img>
标签可以读取动态文件。
一切如何运作(现在):
- 用户发送文件
- nodejs获取二进制数据,以及用户信息。。。但不是mimetype、filename、size
- nodejs向所有用户广播原始二进制文件。(无法指定用户和文件信息)
- 客户端创建了一个bloburl(谁发送的?XD)
编辑
我现在有什么:
客户端1(发送文件)CHROME
fileInput.addEventListener('change',function(e){
var file=this.files[0];
ws.send(new Blob([file],{
type:file.type //<- SET MIMETYPE
}));
//file.size
},false);
注意:file
已经是blob。。。但这就是通常创建指定mimetype的新blob的方式。
服务器(向其他客户端广播二进制数据)NODEJS
aaaaaa和mimetype不见了
ws.addListener('message',function(binary){
var b=0,c=wss.clients.length;
while(b<c){
wss.clients[b++].send(binary)
}
});
客户端2(接收二进制)CHROME
ws.addEventListener('message',function(msg){
var blob=new Blob([msg.data],{
type:'application/octet-stream' //<- LOST
});
var file=window.URL.createObjectURL(blob);
},false);
注意:m.data
已经是blob。。。但这就是通常创建一个新blob的方式,指定mimetype开关丢失。
在客户端2中,我需要mimetype,当然我也需要关于用户的信息,这些信息可以从客户机1或服务器检索(不是一个好的选择)。。。
你有点运气不好,因为Node不支持Blob
接口,所以你用Node以二进制形式发送或接收的任何数据都只是二进制的。你必须有一些知道如何解释Blob对象的东西。
这里有一个想法,让我知道这是否有效。通过阅读websockets'ws
的文档,它表示支持发送和接收ArrayBuffers
。这意味着您可以使用TypedArrays。
这就是它变得令人讨厌的地方。在每个TypedArray
的开头设置一个特定的固定n
字节数,以表示utf8中编码的mime类型或其他类型,而TypedArray
的其余部分包含文件的字节。
我建议使用UInt8Array
,因为utf8
字符有8位长,这样编码时您的文本可能是可读的。至于文件位,你可能只会把它们写在某个地方,并在上面加上一个结尾
另外请注意,无论是从节点还是在浏览器中,这种解释方法都可以双向工作。
这个解决方案实际上只是类型转换的一种形式,您可能会得到一些意想不到的结果。mime类型字段的固定长度至关重要。
在这里进行了说明。复制、粘贴、将图像文件设置为所需的任何内容,然后运行该操作。你会看到我设置的哑剧类型弹出。
var fs = require('fs');
//https://stackoverflow.com/questions/8609289/convert-a-binary-nodejs-buffer-to-javascript-arraybuffer
function toUint8Array(buffer) {
var ab = new ArrayBuffer(buffer.length);
var array = new Uint8Array(ab);
for (var i = 0; i < buffer.length; ++i) {
array[i] = buffer[i];
}
return array;
}
//data is a raw Buffer object
fs.readFile('./ducklings.png', function (err, data) {
var mime = new Buffer('image/png');
var allBuffed = Buffer.concat([mime, data]);
var array = toUint8Array(allBuffed);
var mimeBytes = array.subarray(0,9); //number of characters in mime Buffer
console.log(String.fromCharCode.apply(null, mimeBytes));
});
以下是您在客户端的操作方法:
解决方案A:获取包裹
获取缓冲区,用于浏览器的Node的buffer API的实现。连接字节缓冲区的解决方案将与以前完全一样工作。您可以附加像To:和what not这样的字段。我相信,为了更好地为客户服务,你格式化标题的方式将是一个不断发展的过程。
解决方案B:旧学校
步骤1:将Blob转换为ArrayBuffer
注意:如何将字符串转换为ArrayBuffer
var fr = new FileReader();
fr.addEventListener('loadend', function () {
//Asynchronous action in part 2.
var message = concatenateBuffers(headerStringAsBuffer, fr.result);
ws.send(message);
});
fr.readAsArrayBuffer(blob);
第2步:连接阵列缓冲区
function concatenateBuffers(buffA, buffB) {
var byteLength = buffA.byteLength + buffB.byteLength;
var resultBuffer = new ArrayBuffer(byteLength);
//wrap ArrayBuffer in a typedArray/view
var resultView = new Uint8Array(resultBuffer);
var viewA = new Uint8Array(resultBuffer);
var viewB = new Uint8Array(resultBuffer);
//Copy 8 bit integers AKA Bytes
resultView.set(viewA);
resultView.set(viewB, viewA.byteLength);
return resultView.buffer
}
第3步:接收并重新发送
我不打算重复如何将连接的String字节转换回字符串,因为我在服务器示例中已经做过了,但将文件字节转换为mime类型的blob相当简单。
new Blob(buffer.slice(offset, buffer.byteLength), {type: mimetype});
robnyman
的Gist进一步详细介绍了如何使用通过XHR传输的图像,将其放入本地存储,并在页面上的图像标签中使用。
我喜欢@Breedly的想法,即准备一个固定长度的字节数组来指示ArrayBuffer的mime类型,所以我创建了这个npm包,我在处理websocket时使用它,但其他人可能会觉得它很有用。
示例用法
const {
arrayBufferWithMime,
arrayBufferMimeDecouple
} = require('arraybuffer-mime')
// some image array buffer
const uint8 = new Uint8Array(1)
uint8[0] = 1
const ab = uint8.buffer
const mime = 'image/png'
const abWithMime = arrayBufferWithMime(ab, mime)
const {mime, arrayBuffer} = arrayBufferMimeDecouple(abWithMime)
console.log(mime) // "image/png"
console.log(arrayBuffer) // ArrayBuffer
- 可以't让我的if语句处理js中的html表单输入
- keyup事件处理程序更改焦点不适用于快速键入
- 如何使用jquery处理php循环通过元素
- angular.js没有'无法在PhoneGap中处理视图标记
- Webpack/Rect:遵循egghead.io教程,但出现错误:您可能需要一个合适的加载程序来处理此文件类型
- 提示使用服务器端事件处理程序激活JavaScript
- javascript:如何在antlr生成的Lexer中进行错误处理
- 如何编写一个具有公共标头的批处理
- 在同一个服务工作者中处理service-worker.js有任何影响吗
- 如何处理node.js节点mongodb中的连接和查询队列
- 通过命令行/批处理文件打开页面时,将javascript代码注入Google Chrome
- 如何处理10页以上的静态页眉/页脚
- 将事件处理程序绑定到任何可能的事件
- 通过ajax将坐标传递到php服务器端,并在处理后检索到javascript
- python到“;流“;字典处理
- 使用javascript进行实时图像处理
- 导入jQuery脚本获胜'我不处理html文件
- Javascript无法处理表单提交
- 在承诺链中处理早期回报的最佳方式
- nodejs二进制websocket mimetype处理