Node.jsのExpressでmultipart/form-dataを処理する方法
ExpressでPOSTで送信されたデータを受け取るときになかなかうまくいかなかったので書きました。
フロント:AngularJS
サーバ :Node.js、Express
やろうとしてたことはmultipart/form-dataのデータをアップロードしてました。
POSTでは、body部に送信するデータが詰め込まれているので、サーバ側ではbody部のデータをハンドリングする必要があります。
最初はbody-parserというモジュールを使っていたんですが、データが全然見えなくて結構長い間悩んでましたw
どうやらmultipart/form-dataを扱うためには、body−parserとは別のモジュールを使う必要があるらしいです。
body−parserのREADMEにはこう書いてありました。
Node.js body parsing middleware. This does not handle multipart bodies, due to their complex and typically large nature. For multipart bodies, you may be interested in the following modules: busboy and connect-busboy multiparty and connect-multiparty formidable multer Other body parsers you might be interested in: body co-body
expressjs/body-parser · GitHub
ということで、multerというモジュールを使いました。
コードは以下のとおり。
var express = require('express'); var router = express.Router(); var multer = require('multer'); var app = express(); router.post('/', multer({ dest: 'uploads/'}), function(req, res, next) { res.send(JSON.stringify('hoge')); });
multerを使うと簡単にmultipart/form-dataを取り扱いできる。
ちなみにAngularJSはこんな感じ。
$scope.uploadFile = function(files) { var fd = new FormData(); //Take the first selected file fd.append("file", files[0]); fd.append("parent_id", parent_id); fd.append("storage_type", 1); console.log('parent_id = '+parent_id); //$http.post('/api/file/upload.json', $http.post('http://localhost:3000/upload', fd, { headers: {'Content-Type': undefined }, transformRequest: angular.identity }). success(function(data, status, headers, config) { console.log(data); console.log(status); console.log(headers()); $scope.update(); $modalInstance.close(); }). error(function(data, status, headers, config) { $modalInstance.close(); }); };
一部抜粋なのでよくわからないかもですが、大事なのは
・FormDataオブジェクトを生成している
(multipart/form−dataのデータで、HTMLのformタグのデータと同じ扱われ方をする)
・AngularJSのpostメソッドで送信している
・ headers: {'Content-Type': undefined },
transformRequest: angular.identity
の2行はお約束らしい。
詳しくは
Blog | Multipart/form-data File Upload with AngularJS | Uncorked Studios
こんな感じで、multipart/form-dataをサーバ側に送ってます。