Express.js は、サーバーサイドのJavaScript上で構築することができるNode.jsのWebアプリケーションフレームワークです。バックエンドのサーバとしていろいろな用途で利用されますがファイルアップロード方法を知りたいという人も多いと思います。本文書はExpress.jsを使ってファイルをアップロードしたいけどどのように設定を行えばいいのかわからないという人向けの文書です。ファイルのアップロードはExpress.jsのmulterモジュールを使うことで簡単に行うことができ、バックエンドサーバ上にアップロードしたファイルを保存することができます。

Express.jsではmulter以外にもファイルアップロードを行うことができるモジュールが存在するのでその一つのexpress-fileuploadについても後半に動作確認を行っています。こちらのモジュールも簡単にファイルのアップロードを行うことができます。

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

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

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


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

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

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

Multerモジュールを利用した場合

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

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

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


 $ npm install --save multer

インストールが完了したら今回の動作確認で利用するライブラリ、モジュールのバージョンを確認するためにpackage.jsonファイルを確認します。


{
  "name": "express_backend",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "dependencies": {
    "express": "^4.19.2",
    "multer": "^1.4.5-lts.1"
  },
  "devDependencies": {
    "nodemon": "^3.1.4"
  }
}

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

ファイルのアップロードの入力フォームが記述された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

ポート3000でアクセスできるように設定を行っているのでアップロード画面のURL(http://localhost:3000/upload)にブラウザからアクセスします。

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

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

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

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


uploads $ ls
a9145b2922b7caff0bd80708a65fae63

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

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

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

multerが持つ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フォルダにアップロードしたファイルと同じ名前でファイルが保存されます。

multerモジュールを利用することでこんなに簡単にサーバ上にファイルのアップロードが行えることが確認できました。さらにアップロードしたファイルについて確認をしていきます。

ファイルの情報を取得(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モジュールを利用することでファイルのアップロードが行えることが確認できました。

express-fileuploadを利用した場合

express-fileuploadのインストール

インストールはnpm i express-fileuploadコマンドで行うことができます。


 % npm i express-fileupload

express-fileuploadを利用した場合のコード

multerで動作確認をしたコードをexpress-fileuploadに置き換えています。


const express = require("express");
const path = require("path");
const fileUpload = require("express-fileupload");

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

app.use(fileUpload());

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

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

app.post("/upload", function (req, res) {
  const file = req.files.file;
  file.mv(path.join(__dirname, "public", file.name), function (err) {
    if (err) res.status(500).send(err);
    res.send(file.name + "ファイルのアップロードが完了しました。");
  });
});

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

app.useメソッドを利用してexpress-fileUploadをミドルウェアとして設定しています。ミドルウェアで設定することでアップロードしたファイルはreq.filesの中に保存されます。req.files.fileのfileはupload.htmlファイルのinput要素のnameで設定した名前です。req.files.fileで戻されるオブジェクトにはmvメソッドが含まれているのでmvメソッドを利用して指定したディレクトリにファイルを保存しています。ここではpublicディレクトリの下に直接保存しています。

実際に動作確認するとpublicディレクトリにアップロードしたファイルが保存されることが確認できます。

multerとexpress-fileuploadどちらを利用しても簡単にファイルのアップロードを行うことができます。