目次
前提
要素 | バージョン |
---|---|
node | 7.4.0 |
npm | 4.1.2 |
express | 4.14.0 |
AngularJS | 1.4.1 |
概要
- AngularJSのページから画像ファイルをアップロードし、express側で保存させる
- AngularJSには(少なくとも標準モジュールには)ファイルアップロードの仕組みが存在しないので、ディレクティブを自作して対応する
1.クライアントサイド
添付ファイルをモデルで扱うためのディレクティブを定義
app.directive('fileModel', ['$parse', function($parse) { return function(scope, element, attrs) { const model = $parse(attrs.fileModel); element.bind('change', function() { scope.$apply(() => { model.assign(scope, element[0].files[0]); }); }); }; }]);
上記ディレクティブは、以下のように利用する
<input type="file" name="myfile" file-model="my-file">
上記ディレクティブをinput[type=file]にバインドすることで、ファイル選択時にファイルの内容をAngularモデルにバインディングする。
これによって、添付されたファイルをAngularJSのモデルとして操作できるようになる。
ファイルアップロード用のサービスを定義
app.factory('fileUpload' , ['$http' , function($http) { return { upload(photo) { let formData = new FormData(); formData.append('file' , photo); $http.post('/rest/photo/put', formData, { headers: {'Content-Type': undefined} , transformRequest: null }); }, }; }]);
APIがあるであろう、’/rest/photo/put’に対して添付ファイルをPOSTする。
Content-Typeをundefinedに明示的に設定しておくと、AngularJS側で良い感じに設定してくれるので今回はおまかせする。
transformRequestをnullにしておかないと、POSTデータがJSONに変換される可能性があるので、一応明示的にNULLにしておく。
上記サービスを、添付ファイルを指定して実行することで、APIサーバに添付ファイルがPOSTされる
2.サーバサイド
Multerモジュールをインストール
Multerモジュールは、multipart/form-data形式のリクエストを扱うためのNodeJSのミドルウェア。これを用いることでexpress側で添付ファイルを処理することができる。
$ npm install --save multer
POSTされたファイルを保存する
Multerモジュールがインストールできたら、以下のコードをexpress側に追加する(※appはexpressオブジェクト)
var multer = require('multer'); app.use(multer({ dest: './uploads/'}).any());
非常にシンプルだが、これだけで、アップロードファイルがPOSTされた際に、そのファイルを./uploadsに保存する処理が自動で行われる。
アップロードファイルの検証
アップロードされたファイルは、requestオブジェクトのfiles属性に含まれている。filesは配列であることから、複数ファイルの同時アップロードにも対応できる。
以下のコードでは、アップロードされたファイル(1件)の内容を出力し、無条件でsuccessを戻している。
app.post('/rest/photo/put' , function(req, res) { console.log(req.files[0]); res.send('success'); });
‘/rest/photo/put’に対して、画像ファイルを1件アップロードすると、以下のログが出力される
{ fieldname: 'file', originalname: '10.jpeg', encoding: '7bit', mimetype: 'image/jpeg', destination: './uploads/', filename: '652aa507d6e70b89e064bbddd3b33224', path: 'uploads/652aa507d6e70b89e064bbddd3b33224', size: 5297 }
ユニークなランダム文字列であるfilenameを含んだpathが既に出力に含まれているように、この時点で既に画像ファイルは保存されている。
もちろんファイル名を変更したり、保存する条件を指定したりもできるが、ここでは割愛する。