Node.jsとExpress4の組み合わせでブラウザからサーバにファイルをアップロードする方法をWebで調べたところ、古い情報ばかり出てきて解決までに半日ほどかかりました。この記事では、Express4とmulterモジュールを使ったファイルのアップロード方法についてまとめてみます。
multerモジュールのREADMEを参考にさせていただきました。
前提条件
Expressのバージョンは4.13.4、multerモジュールのバージョンは1.2.0です。
$ express --version
4.13.4
$ npm list multer
xxxx@y.y.y zzzzz
└── multer@1.2.0
ファイルをアップロードするアプリケーションの作成
express-generatorを使って、アプリケーションの雛形を生成します。
$ express file-upload
create : file-upload
create : file-upload/package.json
create : file-upload/app.js
create : file-upload/public
create : file-upload/public/javascripts
create : file-upload/public/images
create : file-upload/public/stylesheets
create : file-upload/public/stylesheets/style.css
create : file-upload/routes
create : file-upload/routes/index.js
create : file-upload/routes/users.js
create : file-upload/views
create : file-upload/views/index.jade
create : file-upload/views/layout.jade
create : file-upload/views/error.jade
create : file-upload/bin
create : file-upload/bin/www
install dependencies:
$ cd file-upload && npm install
run the app:
$ DEBUG=file-upload:* npm start
続いて、package.json
を編集してmulterモジュールを追加します。
{
"name": "file-upload",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"body-parser": "~1.15.1",
"cookie-parser": "~1.4.3",
"debug": "~2.2.0",
"express": "~4.13.4",
"jade": "~1.11.0",
"morgan": "~1.7.0",
"serve-favicon": "~2.3.0",
"multer": "~1.2.0"
}
}
views/index.jade
を編集して、ファイルを選択してサーバにアップロードする画面を作成します。
extends layout
block content
h1= title
form(method="post", enctype="multipart/form-data", action="/upload")
input(type="file", name="thumbnail")
input(type="submit")
クライアントが発行するPOSTリクエストに応じてファイルをアップロードする処理を、routes/index.js
に加えます。
var express = require('express');
var router = express.Router();
var multer = require('multer');
var upload = multer({ dest: './uploads/' }).single('thumbnail');
/* GET home page. */
router.get('/', function(req, res, next) {
res.render('index', { title: 'Express' });
});
router.post('/upload', function(req, res) {
upload(req, res, function(err) {
if(err) {
res.send("Failed to write " + req.file.destination + " with " + err);
} else {
res.send("uploaded " + req.file.originalname + " as " + req.file.filename + " Size: " + req.file.size);
}
});
});
module.exports = router;
multer({ dest: './uploads/' })
で、ファイルのアップロード先のディレクトリを指定します。ファイルを一個だけアップロードする.single()
メソッドを用いる場合、アップロードされたファイルのオブジェクトはreq.file
に格納されます。アップロードしたファイルの名前には、multerモジュールによりランダムな値が設定されます。アップロード前のファイル名はreq.file.orignalname
、アップロード後のファイル名はreq.file.filename
から取得できます。その他、アップロード先のディレクトリをreq.file.destination
から、アップロードしたファイルのサイズをreq.file.size
から取得することができます。
ファイルのアップロード
では、さっそくアプリケーションを起動してみましょう。
$ npm install
npm WARN deprecated jade@1.11.0: Jade has been renamed to pug, please install the latest version of pug instead of jade
npm WARN deprecated transformers@2.1.0: Deprecated, use jstransformer
cookie-parser@1.4.3 node_modules\cookie-parser
├── cookie-signature@1.0.6
└── cookie@0.3.1
...
$ npm start
> file-upload@0.0.0 start C:\Users\IBM_ADMIN\Documents\ITLMC\2016\blog\file-upload
> node ./bin/www
ブラウザでhttp://localhost:3000にアクセスします。
「参照」ボタンからファイルを選んで、送信ボタンを押すと。。。
アップロードの完了時にupload()
メソッドに渡したコールバック関数が呼ばれて、サーバからレスポンスが返ってきました。IMG_4533.JPG
という名前のファイルが2e491eefb9ec7c5858af2f0aba0ecee6
という名前でアップロードされたようです。では、アップロード先として指定した./uploads
ディレクトリの中を見てみましょう。
$ ls -l ./uploads/
合計 188
-rwx------+ 1 smatsui None 188729 9月 28 15:01 2e491eefb9ec7c5858af2f0aba0ecee6
ファイルをアップロードすることができました!