Node.jsからVue.jsクライアントへSocket.ioを通して画像を送信して表示
先日の記事でやったこと。
Node.js
からVue.js
に画像を送信して表示する。
Express
を使わずにSocket.io
だけで行う。
このときbase64
という形式でバイナリデータをテキストファイルに変換して送信した。
次のように動作する。
今回はわざわざデータをbase64
に変換せずともfs
で読み込んだままのバイナリデータをそのままVue.js
へ送信。
クライアント側で処理し画像を表示する。
Socket.io
はバイナリ送信に対応している。
以前と比べて変換するコードが一切ないので非常にスマートとなった。
import io from 'socket.io'
import fs from 'fs'
const socket = io(7000)
socket.on('connection', function (socket) {
console.log(`a user connected[id:${socket.id}]`)
socket.on("get_img", () => {
const filePath = "./images/test_img.jpg"
const imgBinary = fs.readFileSync(filePath) //単純に読み込んで
socket.emit("img_data",(imgBinary)) //そのまま送信
console.log("a image was sent.")
})
})
こちらは変換するコードを実装する必要があるがbase64
関係のヘッダ処理が全て排除できるためコードが短い。
重要なのは「ここに注目!」と書いてある2行だけ。
<template>
<v-container>
<v-btn @click="getImg()">get img</v-btn>
<v-img :src="imgBlobUrl" v-if="imgBlobUrl" />
</v-container>
</template>
<script>
import io from "socket.io-client";
export default {
name: "HelloWorld",
data: () => ({
socket: io("localhost:7000"),
imgBlobUrl: null
}),
mounted() {
this.socket.on("connect", () => {
console.log("connected");
this.socket.on("img_data", imgBinary => {
const blob = new Blob([imgBinary])
this.imgBlobUrl = window.URL.createObjectURL(blob)
});
});
},
methods: {
getImg() {
this.socket.emit("get_img");
}
}
};
</script>
まず、fs
で画像を読み込んだデータを直接送信するとVue.js
にはArrayBuffer
という形式で受信することとなる。
ArrayBuffer
とは要するにバイナリデータなのだが、この生データはブラウザでは直接取り扱うことができない。
当然img
タグのsrc
に放り込んでもエラーが出る。
基本的に他サイトでは難しい解説しかされていないのでとにかく分かりやすくする。
const blob = new Blob([imgBinary]) //[]でくくって配列する必要がある
imgBinary
に送られてきたバイナリデータが入っている。
まずこのままでは数字の羅列なのでデータがどういうものなのか分からない。
そこでBlob
というオブジェクトとしてをnew
することでこれをブラウザから内部的に取り扱える**「ファイル」**になったと考えてもらいたい。
つまりユーザーには取り扱えないがブラウザがアクセスできる仮のフォルダの中に送られてきた画像データが入ったような状態。
this.imgBinary = window.URL.createObjectURL(blob)
blob
データは生成されたのでimg
タグのsrc
に入れてやりたい。しかしそもそもsrc
には何を入れるものだっただろうか。
src
は基本的に**URL
を入れるものであり生データを直接いれるものではない。**
そこでブラウザ側のAPIであるcreateObjectURL
にこのblob
を入れてやるとそのblob
にアクセスできるURL
が発行される。
つまりこれをimg
タグのsrc
に入れてやればようやくブラウザが画像として取り扱うことができるわけだ。
コード量でみれば圧倒的に短くなった。
更にデータ通信量も30%削減されるらしい。
非常に簡単だった。
今後はできる限りこちらでデータを扱っていきたい。