のらぬこの日常を描く

ノージャンルのお役立ち情報やアニメとゲームの話、ソフトウェア開発に関する話などを中心としたブログです。

nodejs+expressで自PCにオレオレあぷろだをつくる

こんにちは。のらぬこです。

何回かに分けて、僕が持っている4種類のゲーム機(PS3、PS4、PSvita3DS)のスクショ画面をPCにネットワーク経由で取り込む話をしました。

いずれのハードも、一旦インターネット上の何処かにファイルをアップロードし、PCからそれを取り出すというやり方で実現可能という内容でした。

でも、外部のサービスを利用しなくても、自分のPCにWebサーバを立てれば、ゲーム機のWebブラウザから自分のPCに接続し、スクショ画像を自分のPCに直接アップロードすることができるようになります。

今回は、自PCでオレオレあぷろだを立ち上げ、ゲーム機で撮ったスクショを自PCに直接アップロードできるような仕組みを作りたいと思います。

3DSのみ、スクリーンショットの保存方法が特殊なため、今回記載する方法は使えません。
ただし、ゲーム内にスクリーンショット保存機能を持つ一部のゲーム(ファンタジーライフリンクやドラゴンクエスト8等)や、3DSカメラで撮影した写真等は、今回紹介する方法を使用して、画像データをPCに直接アップロードすることが可能です。

開発言語をどうするかはちょっとだけ悩んだのですが、昔、nodejsを使うと簡単にWebサーバがたてられるみたいな記事をどこかで見たのを思い出し、nodejsで書いてみることにしました。

とりあえず「nodejs ファイル アップロード」でググってコピペで動かしてみようって思ったのですが、意外と動かず苦労しました。

開発・実行環境

前準備

  • 必要なモジュールをインストールし、expressのひな型プロジェクトを作成します。
C:\DATA>npm --version
3.10.8

C:\DATA>npm install -g express
`-- express@4.14.0

C:\DATA>npm install -g express-generator
`-- express-generator@4.14.0

C:\DATA>express uploader

C:\DATA>cd uploader && npm install
  • multer モジュールを プロジェクトに追加します

package.jsonを以下のように編集します。

{
  "name": "uploader",
  "version": "0.0.0",
  "private": true,
  "scripts": {
    "start": "node ./bin/www"
  },
  "dependencies": {
    "body-parser": "~1.15.2",
    "cookie-parser": "~1.4.3",
    "debug": "~2.2.0",
    "express": "~4.14.0",
    "jade": "~1.11.0",
    "morgan": "~1.7.0",
    "serve-favicon": "~2.3.0",
    "multer": "~1.2.0"    // <=== 追加
  }
}

編集が終わったらモジュールをインストールします

C:\DATA\uploader>npm install
  • ここまでの作業の動作確認をする

まず、Webサーバを起動します。

C:\DATA\uploader>npm start

> uploader@0.0.0 start C:\DATA\uploader
> node ./bin/www

Webブラウザで http://localhost:3000/ に接続すると、以下のような画面が表示されるはずです。」 f:id:noranuk0:20161118001601p:plain

また、コマンドプロンプト(コンソール)には以下のようなログが出力されるはずです。

GET / 200 420.317 ms - 170
GET /stylesheets/style.css 200 6.069 ms - 111

ここまで確認できたら、コマンドプロンプト上で CTRL+C を押し、サーバを停止します。

補足

express は軽量webサーバを作るためのモジュール、express-generatorはexpressのためのひな型プロジェクトを生成するためのモジュールです。

また、multerは form-dataを扱うためのモジュールです。

実装

まずはファイルのアップロード先ディレクトリを作ります

C:\DATA\uploader>mkdir uploads

次に、ファイルアップロード画面のWebページを作成します。 views/index.jade を以下のように編集します。

extends layout

block content
  form(method="post", enctype="multipart/form-data", action="/")
      input(type="file", name="uploadedfile")
      input(type="submit")

最後にapp.js を編集し、formがpost 際の動作を実装します。

var express = require('express');
var path = require('path');
var favicon = require('serve-favicon');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');

// 以下の行追加
var multer = require('multer');

var index = require('./routes/index');
var users = require('./routes/users');

var app = express();

// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');

// uncomment after placing your favicon in /public
//app.use(favicon(path.join(__dirname, 'public', 'favicon.ico')));
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));

app.use('/', index);

// 追加ここから >>>>
var storage = multer.diskStorage({
          destination: function (req, file, cb) {
                      cb(null, './uploads')
                    },
          filename: function (req, file, cb) {
                      cb(null, '[' + Date.now() + ']' + file.originalname)
                    }
});
var upload = multer({ storage: storage });

app.post('/', upload.single('uploadedfile'), function (req, res) {
        console.log(req.file);
        res.redirect(301, '/');
});
// 追加ここまで <<<<

app.use('/users', users);

// catch 404 and forward to error handler
app.use(function(req, res, next) {
  var err = new Error('Not Found');
  err.status = 404;
  next(err);
});

// error handler
app.use(function(err, req, res, next) {
  // set locals, only providing error in development
  res.locals.message = err.message;
  res.locals.error = req.app.get('env') === 'development' ? err : {};

  // render the error page
  res.status(err.status || 500);
  res.render('error');
});

module.exports = app;

よその記事を見ると、multer オブジェクトの生成部分を
var upload = multer({ dest: 'uploads/' });
のように書いているところが多いのです。

しかし、この書き方ではアップロード後のファイル名の指定ができず
保存されたファイル名が、be167931b87cc96e66986ae97df4a85f のようになってしまいます。

ファイル名のカスタマイズ(例えば、アップロード時のファイル名で保存する等)方法は github内のreadme に書かれています。

GitHub - expressjs/multer: Node.js middleware for handling `multipart/form-data`.

動かしてみる

webサーバを起動し、ブラウザから http://localhost:3000/ にアクセスします。

アップロードしたいファイルを適当に選択し、[クエリー送信]ボタンを押すと、ファイルがプロジェクトディレクトリ内の uploads ディレクトリにアップロードされます。 f:id:noranuk0:20161118013335p:plain

もちろん、ゲーム機やスマホからも接続できます。

他のPCなどから接続するときは http://192.168.1.10:3000/ のように今回作ったWebサーバを立てたPCのIPアドレスを指定してください。

ローカルip 確認 - Google 検索

以下、new nintendo 3DSの場合です。

f:id:noranuk0:20161118084316j:plain f:id:noranuk0:20161118084324j:plain f:id:noranuk0:20161118084331j:plain f:id:noranuk0:20161118014403j:plain

ということで、無事、当初の目的が達成できました。

最後までお読みいただいてありがとうございます。

この記事が何かの役に立てば幸いです。

それでは。

続編書きました。登録済のファイル一覧の表示ができるようになっています。

noranuk0.hatenablog.com