本文書はExpressを使ってファイルをアップロードしたいけどどのように設定を行えばいいのかわからないという人向けの文書です。Expressのmulterモジュールを使うことで簡単にファイルのアップロードを行いサーバ上にアップロードしたファイルを保存することができます。

ExpressサーバはNode.js上で構築するバックエンドサーバなのでExpressを利用するためにはNode.jsのインストールが必要になります。Node.jsやExpressについては下記の文書で公開しているのでぜひ参考にしてみてください。

Expressの環境

ファイルアップロードの動作確認を行うためのExpressの設定を行います。任意の名前のフォルダを作成します。本文書ではexpress_file_uploadという名前をつけます。作成したフォルダに移動してnpm init -yコマンドを実行してpackage.jsonファイルを作成します。


 % npm init -y
Wrote to /Users/mac/Desktop/express_file_upload/package.json:

{
  "name": "express_file_upload",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC"
}

npm installコマンドでexpressをインストールします。


 % npm install express

インストールが完了したらindex.jsファイルを作成して下記のコードを記述します。


const express = require('express');

const app = express();
const port = 3000;

app.get('/', (request, response) => response.send('Hello World!'));

app.listen(port, function () {
  console.log(`Example app listening on port ${port}!`);
});

ファイルの更新を検知してファイルのリロードを自動で実行できるようにnodemonのインストールを行います。


 % npm install nodemon --save-dev

インストールしたnodemonを利用してExpressを起動します。


 % npx nodemon index.js
[nodemon] 2.0.15
[nodemon] to restart at any time, enter `rs`
[nodemon] watching path(s): *.*
[nodemon] watching extensions: js,mjs,json
[nodemon] starting `node index.js`
Example app listening on port 3000!

ブラウザでlocalhost:3000にアクセスして”Hello World”が表示されたらExpressの起動は正常に行われています。

HTMLファイルなどの静的なファイルを保存するためにプロジェクトフォルダの直下にpublicフォルダを作成します。

Multerモジュールのインストール

Expressでファイルのアップロードを行うためにmulterモジュールのインストールを行います。

インストールは、npm installコマンドを使って行います。


 $ npm install multer

ファイルアップロード画面の作成

ファイルのアップロードの入力フォームが記述されたHTMLファイルをpublicフォルダの下に作成します。名前をupload.htmlとし、ファイル選択と送信ボタンがついただけのシンプルな送信フォームです。


<!DOCTYPE html>
<html lang="ja"></html>
<head>
    <meta charset="UTF-8">
    <title>Express.js File Upload</title>
</head>
<body>
    <h1>ファイルアップロード</h1>
    <form action="/upload" method="POST" enctype="multipart/form-data">
        <input type="file" name="file">
        <button type="submit">送信</button>
    </form>
</body>
</html>

multerの設定

インストールしたmulterモジュールはrequireを利用して読み込みます。アップロードしたファイルの保存先はuploadsとしpublicフォルダの下にuploadsフォルダを作成します。


const multer = require('multer')
const upload = multer({ dest: 'public/uploads/' })

ルーティングの設定

アップロード画面を表示させるためのルーティングを追加します。ファイルを戻す場合にはsendFileメソッドを利用します。sendFileメソッドの引数には戻すファイルのパスを設定します。ファイルは先ほど作成したpublic/upload.htmlを指定しています。パスの設定にはpathモジュールを利用しています。


app.get('/upload', (req, res) => res.sendFile(path.join(__dirname, 'public/upload.html')))	

アップロードしたファイルを保存するためのコードは下記の通りです。upload.htmlファイルでは/uploadに対してPOSTリクエストを送信します。


app.post('/upload', upload.single('file'), function (req, res, next) {
    res.send('ファイルのアップロードが完了しました。');
  })

Uploadを行うためのJavaScriptコード

ファイルアップロードに必要な全体のコードは下記の通りです。publicフォルダの静的ファイルにアクセスできるようにミドルウェアのexpress.staticを設定しています。


const express = require('express')
const path = require('path')
const multer = require('multer')

const app = express()
const port = 3000

const upload = multer({ dest: 'public/uploads/' })

app.use(express.static(path.join(__dirname, 'public')))

app.get('/', (request, response) => response.send('Hello World!'))

app.get('/upload', (req, res) => res.sendFile(path.join(__dirname, 'public/upload.html')))

app.post('/upload', upload.single('file'), function (req, res) {
    res.send(req.file.originalname + 'ファイルのアップロードが完了しました。');
  })

app.listen(port,function(){
	console.log(`Example app listening on port ${port}!`)
})	

ここまででアップロードを行うための準備は完了です。

ファイルのアップロード

ファイルをアップロードする前にExpressの起動を行います。


 $ npx nodemon index.js

アップロード画面のURL(lupl)にブラウザからアクセスします。

ファイルアップロード画面
ファイルアップロード画面

入力フォーム画面からファイルを選択し、送信ボタンを行うとアップロードが行われます。ファイルのアップロードが成功すると以下の完了画面が表示されます。express_img_src.pngがアップロードしたファイルの名前です。

アップロード完了画面
アップロード完了画面

uploadsフォルダを確認すると新規でファイルが保存されていることが確認できます。作成されるファイルは自動で名前がつけられ、ランダムで拡張子はありません。これがアップロードされたファイルです。


uploads $ ls
a9145b2922b7caff0bd80708a65fae63

ブラウザからlocalhost:3000/uploads/a9145b2922b7caff0bd80708a65fae63にアクセスするとミドルウェアのexpress.staticを設定しているのでファイルのダウンロードが行われます。拡張子はありませんがダウンロードしたファイルを確認すると画像ファイルであることがわかります。

ファイル名を変更して保存(diskStorage)

先ほどの方法ではファイル名はランダムな名前で拡張子もついていませんでした。アップロードしたファイル名と同じファイル名で保存させるためにmulterのdiskStorageを利用します。

diskStorageを追加しファイル名を変更するための設定を行います。

ファイルの保存先はuploadsでファイル名はfile.originalnameでアップロードしたファイル名と同じ名前になるように設定を行なっています。


const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    cb(null, 'public/uploads/')
  },
  filename: function (req, file, cb) {
    cb(null, file.originalname)
  }
})

// const upload = multer({ dest: 'public/uploads/' })
const upload = multer({ storage: storage })

ファイル更新後に再度ファイルのアップロードを実行するとuploadsフォルダにアップロードしたファイルと同じ名前でファイルが保存されます。

ファイルの情報を取得(req.file)

アップロードしたファイルの情報を知りたい場合はreq.fileでアクセスすることができます。req.fileはオブジェクトです。


app.post('/upload', upload.single('file'), function (req, res, next) {
  console.log(req.file);
  res.send('ファイルのアップロードが完了しました。');
});

ファイルをアップロードするとコンソールにreq.fileの中身が表示されます。ファイル名だけではなく保存したパス名も表示されるのでこの情報を利用してデータベースに画像のパスを保存することもできます。


Example app listening on port 3000!
{
  fieldname: 'file',
  originalname: 'vue.jpg',
  encoding: '7bit',
  mimetype: 'image/jpeg',
  destination: 'public/uploads/',
  filename: 'vue.jpg',
  path: 'public/uploads/vue.jpg',
  size: 12841
}

ブラウザからlocalhost:3000/uploads/vue.jpgにアクセスするとアップロードした画像が画面に表示されます。

Expressとmulterモジュールを利用することでファイルのアップロードが行えることが確認できました。