ファイルのアップロードというか写真のアップロードをしたい。
クライアント側Angular
private readFile(file: any) {
const reader = new FileReader();
reader.onloadend = () => {
const formData = new FormData();
const imgBlob = new Blob([reader.result], {type: file.type});
formData.append('file', imgBlob, file.name);
this.postData(formData);
};
reader.readAsArrayBuffer(file);
}
private postData(formData: FormData) {
this.http.post("http://192.168.230.22:8080/v1/user_photo", formData)
.catch((e) => this.handleError(e))
.map(response => response.text())
.finally(() => this.loading.dismiss())
.subscribe(ok => this.showToast(ok));
}
サーバ側Express
req.bodyでも、req.filesでも、中身を取得できないと悩む始末
reqの内容をダンプしてみている
api | headers:
api | { connection: 'upgrade',
api | 'x-forwarded-for': '172.28.0.1',
api | host: '192.168.230.22',
api | 'content-length': '17985467',
api | 'content-type': 'multipart/form-data; boundary=----WebKitFormBoundaryWxpDgOaYBsqFrsAB',
api | origin: 'file://',
api | accept: 'application/json, text/plain, */*',
api | 'user-agent': 'Mozilla/5.0 (iPhone; CPU iPhone OS 10_3_3 like Mac OS X) AppleWebKit/603.3.8 (KHTML, like Gecko) Mobile/14G60',
'content-type': 'multipart/form-data
Expressのapp.jsには、body-parserが入っています。
これが曲者。
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
body-parserのモジュールは、jsonとurlencode済みのものしか扱いません。ファイルアップロードのようにmultipartのものは扱わないのです。
なので、上記部分をコメントアウトか、パスによって分岐をするかして、ファイルアップロードの際には適用しないようにする
以下では、ContentTypeで適用
// parse application/json
app.use(bodyParser.json({ type: 'application/*+json' }));
// parse application/x-www-form-urlencoded
app.use(bodyParser.urlencoded({
extended: false,
type: 'application/x-www-form-urlencoded'
}));
multer
いくつかファイルアップロードライブラリがあるので、お好みで。
今回はmulterを利用。以下に簡単サンプルコード。
express/uploadにファイルが作られます
var multer = require('multer');
var upload = multer({ dest: 'uploads/' })
router.post('/user_photo', upload.any(), (req, res, next) => {
logger.info(req.files);
res.status(200).end();
});
log出力内容
api | 2017-08-15T12:33:57+0000 <info> api.js:269 (router.post) [ { fieldname: 'file',
api | originalname: 'cdv_photo_015.png',
api | encoding: '7bit',
api | mimetype: 'null',
api | destination: 'uploads/',
api | filename: '1f73e8b4197b863716f6b21b447551e9',
api | path: 'uploads/1f73e8b4197b863716f6b21b447551e9',
api | size: 18025712 } ]