[Node.js] express + Multer を使用してファイルアップロード API を作成する

はじめに

こんにちは。モバイルアプリサービス部の平屋です。

本記事では Node.js + express + Multer を使用して (簡易的な) ファイルアップロード API を作成する手順を紹介していきます。

要件など

  • POST multipart/form-data リクエストを受け付ける
  • API はモバイルアプリから使用する
  • モバイルアプリの動作検証が目的なので、簡単に作れそうな方法が良い

検証環境

  • macOS 10.12.3 (16D32)
  • Node.js v6.10.0
  • nvm 0.33.1
  • express 4.14.1
  • Multer 1.3.0

目次

  • 1.Node.js をインストール
  • 2.express-generator をインストール
  • 3.アプリケーション作成
  • 4.パッケージをインストール
  • 5.Multer を追加
  • 6.routes/index.js を修正
  • 7.動作確認

1. Node.js をインストール

任意の方法で Node.js をインストールします。

2. express-generator をインストール

express は Node.js 向けの Web フレームワークで、express-generator は express アプリケーション(express を使用した Node.js アプリケーション) のジェネレータです。

次のコマンドを使用して、express-generator をインストールします。

$ npm install express-generator -g
/Users/hirayashingo/.nvm/versions/node/v6.10.0/bin/express -> /Users/hirayashingo/.nvm/versions/node/v6.10.0/lib/node_modules/express-generator/bin/express
/Users/hirayashingo/.nvm/versions/node/v6.10.0/lib
└─┬ express-generator@4.14.1
  ├─┬ commander@2.9.0
  │ └── graceful-readlink@1.0.1
  ├─┬ mkdirp@0.5.1
  │ └── minimist@0.0.8
  └── sorted-object@2.0.1

3. アプリケーション作成

任意のディレクトリに移動し、express <アプリケーション名> コマンドを使用して express アプリケーションの雛形を作成します。

$ express uploader

  warning: the default view engine will not be jade in future releases
  warning: use `--view=jade' or `--help' for additional options


   create : uploader
   create : uploader/package.json
   create : uploader/app.js
   create : uploader/views
   create : uploader/views/index.jade
   create : uploader/views/layout.jade
   create : uploader/views/error.jade
   create : uploader/public
   create : uploader/public/stylesheets
   create : uploader/public/stylesheets/style.css
   create : uploader/routes
   create : uploader/routes/index.js
   create : uploader/routes/users.js
   create : uploader/bin
   create : uploader/bin/www

   install dependencies:
     $ cd uploader && npm install

   run the app:
     $ DEBUG=uploader:* npm start

   create : uploader/public/images
   create : uploader/public/javascripts

4. パッケージをインストール

手順 3 を行なった段階では、アプリケーション実行のために必要なパッケージはインストールされていません。

npm install コマンドを使用してパッケージをインストールします。npm は Node.js のパッケージを管理するためのツールで、Node.js をインストールすると一緒にインストールされます。

$ cd uploader
$ npm install

コマンドを実行すると、手順 3 で生成された package.json 内に記述されたパッケージが、<アプリケーションディレクトリ>/node_modules の中にインストールされます。

$ ls node_modules
accepts     content-type    graceful-readlink mkdirp      setprototypeof
acorn     cookie      http-errors   morgan      source-map

...

この時点での package.json は以下のようになっています。

{
  "name": "uploader",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.16.0",
    "cookie-parser": "~1.4.3",
    "debug": "~2.6.0",
    "express": "~4.14.1",
    "jade": "~1.11.0",
    "morgan": "~1.7.0",
    "serve-favicon": "~2.3.2"
  }
}

5. Multer を追加

Multer は multipart/form-data 形式のリクエストを扱うための Node.js ミドルウェアです。

以下のコマンドを実行すると、Multer のインストールと package.json への追記が行われます。

$ npm install --save multer

package.json の dependencies の中に multer が追加されました。

{
  ...

  "dependencies": {
    ...

    "multer": "^1.3.0",

    ...
  }
}

6. routes/index.js を修正

routes ディレクトリ内の index.js を修正して、POST リクエストを受け付けられるようにします。

以下のように、5-16 行目と 25-27 行目を追加します。

var express = require('express');
var router = express.Router();

// 追加 1
var multer = require('multer');
var storage = multer.diskStorage({
  // ファイルの保存先を指定
  destination: function (req, file, cb) {
    cb(null, '')
  },
  // ファイル名を指定(オリジナルのファイル名を指定)
  filename: function (req, file, cb) {
    cb(null, file.originalname)
  }
})
var upload = multer({ storage: storage })
//

/* GET home page. */
router.get('/', function(req, res, next) {
  res.render('index', { title: 'Express' });
});

// 追加 2
router.post('/', upload.single('file'), function(req, res) {
  res.json({ 'result': 'success!' });
});
// 

module.exports = router;

5-16 行目では、Multer のロード/作成、保存先/ファイル名の指定を行なっています。アップロードされたファイルはプロジェクトのルートディレクトリに保存されます。

また 25-27 行目は、以下を満たすリクエストに対して応答し、固定の json を返すコードです。

  • ルート (/) に対する POST リクエスト
  • name に「file」を指定したファイルのアップロード

7. 動作確認

アプリケーションを実行

以下のコマンドを実行して express アプリケーションを実行します。Web サーバーが起動し、ポート 3000 でリクエストを受け付けるようになります。

$ npm start

> uploader@0.0.0 start /Users/hirayashingo/Projects/uploader
> node ./bin/www

ブラウザで http:<Web サーバーを起動しているマシンのIPアドレス>:3000/ にアクセスすると、以下のようなページが表示されます。

node-express-multer-file-upload-1

iOS アプリからファイルをアップロードする

iOS アプリの場合、以下のような実装でファイルをアップロードできます。

iOS + Swift + Alamofire

func upload() {
    let path = Bundle.main.path(forResource: "image", ofType: "jpg")
    let fileURL = URL.init(fileURLWithPath: path!)

    Alamofire.upload(
        multipartFormData: { multipartFormData in
            multipartFormData.append(fileURL, withName: "file")
    },
        to: "http://192.168.0.11:3000/",
        encodingCompletion: { encodingResult in
            switch encodingResult {
            case .success(let upload, _, _):
                upload.responseJSON { response in
                    debugPrint(response)
                }
            case .failure(let encodingError):
                print(encodingError)
            }
    }
    )
}

iOS + Objective-C + AFNetworking

- (void)upload
{
    NSString *path = [[NSBundle mainBundle] pathForResource:@"image" ofType:@"jpg"];
    NSURL *fileURL = [NSURL fileURLWithPath:path];

    AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
    [manager POST:@"http://192.168.0.11:3000" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
        [formData appendPartWithFileURL:fileURL
                                   name:@"file"
                                  error:nil];
    } progress:nil success:^(NSURLSessionTask *task, id responseObject) {
        NSLog(@"success");
    } failure:^(NSURLSessionTask *task, NSError *error) {
        NSLog(@"error:%@", error.localizedDescription);
    }];
}

動作結果

iOS アプリからアップロード操作を行い、express アプリケーションのルートディレクトリにファイルがアップロードされることを確認できました。

node-express-multer-file-upload-2

さいごに

本記事では Node.js + express + Multer を使用してファイルアップロード API を作成する手順を紹介しました。

アップロードを受け付ける機能だけであれば本当に簡単に作れますね!

今回解説したサンプルアプリケーションは以下のリポジトリで公開しています。

参考資料