node.jsでsocket.ioを使ってファイルをアップロードする(自称)最小コード

 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なので失敗した場合ちょっと面倒).

 以上です.