node.jsでsocket.ioによる,websocketを経由したファイルアップロードのサンプルです.input type="file"の要素からバイナリのファイルをjsで取り出し,emitでサーバに送るという形です.
今回は,「とりあえずwebsocketでファイルを送りたい!!」というのを試すための,本当に必要最低限なコードのみを用意しました.参考になれば幸いです.
クライアントサイド
html
inputのでtypeがfileな要素を一つ,用意します.
<input type="file" id="fileInput"></input>
js
まず,先ほどのinputにセレクタで,イベントを仕掛けます.このイベントは「inputの内容に変更があったら」です.つまり,変更があると自動的にファイルをアップロードする仕掛けです.
$(document).ready(function(){ $("#fileInput").change(function(event){ var file = event.target.files[0]; upload(file);//ファイルを送る関数 }); });
そしてupload関数がこれです.
function upload(file){ var fileReader = new FileReader(); var send_file = file; //var type = send_file.type;//♪L( ՞ਊ ՞)┘└( ՞ਊ ՞)」♪ var data = {}; fileReader.readAsBinaryString(send_file); fileReader.onload = function(event) { data.file = event.target.result; data.name = "uploadFile"; //data.type = type;//♪L( ՞ਊ ՞)┘└( ՞ਊ ՞)」♪ socket.emit('upload',data); } }
♪L( ՞ਊ ՞)┘└( ՞ਊ ՞)」♪こいつらがいるところのコメントアウトは,ファイルタイプを見るためのものです.今回は本当にサーバにデータを送る最低限のコードなので省略.クライアントサイドはこれで終わり.
サーバサイド
すでにsocket.ioとコネクションは貼られていると仮定します.
クライアントからは,socket.emit('upload',data);でサーバに送っています.ではuploadという名前のemit受取り処理を書きます.fsモジュールを使います.
socket.on('upload', function(data) { var fs = require('fs'); var writeFile = data.file; var writePath = './public/images/test.jpg';//Σ(゚д゚) エッ!? var writeStream = fs.createWriteStream(writePath); writeStream.on('drain', function () {} ) .on('error', function (exception) { //エラー処理 console.log("exception:"+exception); }) .on('close', function () { //(☞三☞三☞՞ਊ՞)☞三☞三☞書き込み完了時の処理 }) .on('pipe', function (src) {}); writeStream.write(writeFile,'binary');//バイナリでお願いする writeStreamend(); //✌( ◔౪◔)✌<ここに書き込み終了時の処理はかかないで });
Σ(゚д゚) エッ!? てところでfileの書き出しパスを指定しているわけですが,「.jpg」としています..jpgのファイルのみ送られるのを期待してるわけですが,全く現実的ではないので,この部分はファイル形式を決定する処理が必要です.今回のクライアントには♪L( ՞ਊ ՞)┘└( ՞ਊ ՞)」♪のところでファイルの形式を見ているところがありました.あの部分を活かしてサーバで処理を書けば大丈夫です.ただし,ちゃんとファイルの形式を制限してサーバに書き込むようにしないと,脆弱性の原因になるので注意が必要です.また,ファイルサイズによる制限も必要になるでしょう.
(☞三☞三☞՞ਊ՞)☞三☞三☞こいつがいるところに,ファイル書き込み完了時に走らせる処理を書きます.例えば,クライアントにemitするとか,データベースに何か値を書くとかです.この処理は,✌( ◔౪◔)✌の居る所に書いてはいけません.node.jsはノンブロッキングI/Oなので,この処理は非同期処理です.✌( ◔౪◔)✌に書くと,書き込みが終わっていないのに処理が走ってしまいます.
本当に最小限しか書いていません.実際はサーバから成功,失敗の処理を返さねばならないでしょうし,それによってクライアントの描画を変えたりとか,fileInputのvalを空にするとか色々考えられます(changeなので失敗した場合ちょっと面倒).
以上です.