背景
Node.jsという最近キテそうな言語を使いこなして、高級寿司を食えるかっこいいエンジニアになりたいので勉強がてらシンプルなWebアプリケーションを作った。あと、WebアプリケーションらしくHerokuにもデプロイしたいと思った。
JEPG画像のアップロードなんで余裕でしょって思っていたらめちゃくちゃ躓いたので、すべての記憶を失っているであろう未来の僕に対して作り方を残す。ごちゃごちゃ書きます。
環境
OS:Windows 10 Pro (64bit)
プロセッサ: Core i5 3.20 GHz
メモリ: 24.0 GB
$ express --version
4.16.1
作り方
1. express-generatorを使う
「巨人の肩に乗っていけぇ~」ということで
こちらの通りにやると大体できました。
[Node.js] express + Multer を使用してファイルアップロード API を作成する
ほんと神、ありがとうございます....
はじめます。
まずは、express-generator をインストールします。
$ npm install express-generator -g
express-generatorというのは、Node.jsで開発するときのフォルダ構成とかjsファイルとかのテンプレート(スケルトンともいうらしい)を作ってくるようなもののようです。
任意のディレクトリで下記を実行することで実際のフォルダやファイルを作ってくれます。
ここでは"testproject"という名前でフォルダを作成し、オプションの「-e」でEJSのテンプレートエンジンを指定します。
テンプレートエンジンにはEJS以外にもJadeとかいろいろあるみたいですが、それぞれHTML形式で記述できるそうです。HTMLぽくかけてJavascriptのコードを入れたり、変数の受け渡しとかも簡単に書けちゃうやつみたいな認識です。てか、ここではHTMLファイルの変わりとして使います。詳しくやるとGlupとかいうのも出てくるみたいです。
$cd testproject
$ls
> bin/ public/ routes/ views/ app.js package.json
上記のようなフォルダができているはずです。
また、npm install を実行し、アプリケーション実行に必要な各種パッケージをインストールします。
$npm install
$ls
> bin/ node_modules/ public/ routes/ views/ app.js package.json
おなじみのnode_modulesフォルダができたことを確認します。
この時点で
をしてブラウザからhttp://localhost:3000/
にアクセスすれば下記のような表示が出るはずです。
![image.png]()
ちなみにここで表示されているのは
views/index.ejsのHTMLとroutes/index.jsで"title"という変数で渡した"Express"という文字列です。
なので、routes/index.jsで"Express"という文字列を"ぱんぱかぱーん"とかにすれば、ブラウザでも"ぱんぱかぱーん"と表示されるはずです。
routes/index.js
.../* GET home page. */router.get('/',function(req,res,next){res.render('index',{title:'Express'});//←ここに指定したindex.ejsと変数titleに指定した文字列がブラウザに返され表示});...
views/index.ejs
...
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
</body>
...
ちょっとしたWebサイトならこれでできるね。ぱんぱかぱーん。
2. Multerを使う
続いて、アップロードされた画像を受け取る際に使うMulterというモジュールをインストールします。
(正確に言うとmultipart/form-data というデータ形式を扱うためのようですが、詳しいことは知りません)
$ npm install --save multer
package.json の dependencies の中に multer が追加されていることを確認。
$cat package.json
>{
"name": "testproject",
"version": "0.0.0",
"private": true,
"scripts": {
"start": "node ./bin/www"
},
"dependencies": {
"cookie-parser": "~1.4.4",
"debug": "~2.6.9",
"ejs": "~2.6.1",
"express": "~4.16.1",
"http-errors": "~1.6.3",
"morgan": "~1.9.1",
"multer": "^1.4.2"
}
}
3. routes/index.js を修正
ここは参考記事から少し変更。
routes/index.js
xpress=require('express');varrouter=express.Router();//*** 追加1 ここから***//varmulter=require('multer');varstorage=multer.diskStorage({//ファイルの保存先を指定(ここでは保存先は./public/images) //Express4の仕様かなんかで画像staticなファイルを保存するときはpublic/以下のフォルダに置かないとダメらしい//詳しくは express.static public でググろう!destination:function(req,file,cb){cb(null,'./public/images/')},//ファイル名を指定//ここでは image.jpg という名前で保存filename:function(req,file,cb){cb(null,'image.jpg')}})varupload=multer({storage:storage})//*** 追加1 ここまで ***///* GET home page. */router.get('/',function(req,res,next){res.render('index',{title:'Express'});});//*** 追加2 ここから ***////ルート (/) に対する POST リクエスト//name タグにfileを指定したもののみ受け付けるrouter.post('/',upload.single('file'),function(req,res){res.json({'result':'success!'});});//*** 追加2 ここまで ***//module.exports=router;
参考記事からの変更点
- 保存先を'/'(ルート)から'./public/images/'に変更。
- 保存名をfile.originalnameからimage.jpgに変更。
一応、ブラウザからもう一度確認しましょう。
ちょろめからhttp://localhost:3000/にアクセス!
3. 画像をPOSTする(アップロードする)
POSTするのはmultipart/form-data というデータ形式なら何でもヨシッ!
「POST?multipart/form-data?何それおいしいの?」状態で、僕にはよく分からなかったので、そういう人向けにツールを使う方法とindex.ejsを書き換えて送信する方法を書きます。
3.1, Fiddlerを使う(とりあえずテストするには、簡単なほう)
FiddlerというツールでPOSTだったりGETを送ることができます。
(本来はパケットキャプチャとかするのかな?)
とりあえず、インストールして起動したら、次の順で画像の赤枠部分を変更してきます。
0.npm startでサーバーを立ち上げる
1.Composerタブを開く
2.リクエストを"POST"に変更
3.送信先を"localhost:3000"に書き換え
4.RequestBody枠の右上にある青字"Upload file..."から送信する画像を選択する
5.RequestBodyのnameを"file"に変更する
(routes/index.jsでname="file"を受け付けるように指定しているため)
6.ExecuteでPOSTリクエストをサーバーに送る。
7.localhost:3000 にアクセスして{ 'result': 'success!' }が表示されているのを確認する。
8.public\images 配下にimage.jpg が保存されていることを確認する。
9.image.jpgを開いて無事に送った画像が表示されていればOK!
![無題.png]()
3.2. 送信用にindex.ejsを書き換える(実際にWebアプリにするなら必要なほう)
views/index.ejsを下記のように書き換えます。
特に注意なのはname=fileになっていることだけ注意してください。
fileになっていないとサーバー側で受け取れません。
(route/index.jsでname=fileを受け付けるように記述しているため)
views/index.ejs
<!DOCTYPE html>
<html>
<head>
<title><%= title %></title>
<link rel='stylesheet' href='/stylesheets/style.css' />
</head>
<body>
<h1><%= title %></h1>
<p>Welcome to <%= title %></p>
<form action="/" method="post" enctype="multipart/form-data">
画像ファイル選択<br>
<input type="file" name="file">
<br>
<input type="submit" name="botan" value="送信">
</form>
</body>
</html>
1.ちょろめからhttp://localhost:3000/にアクセス!
2.画像ファイルを選択して、「送信」ボタンを押す。
3.public\images 配下にimage.jpg が保存されていることを確認する。
4.image.jpgを開いて無事に送った画像が表示されていればOK!
4. アップロード後に表示させる
アップロードした画像をその場で表示するようにします。
具体的にはviewsの配下にimage.ejsという表示用のejsファイルを新規で作成し、それをレスポンスするようにします。
といってもこれだけです。
参照する画像名は固定でimage.jpgとしているのでそれを参照して表示するだけです。
views/image.ejs
<!DOCTYPE html>
<html>
<body>
<h1>画像アップロードしました</h1>
<img src="/images/image.jpg" />
</body>
</html>
また、routes/index.jsを少し修正します。
routes/index.js
xpress=require('express');varrouter=express.Router();//*** 追加1 ここから***//varmulter=require('multer');varstorage=multer.diskStorage({//ファイルの保存先を指定(ここでは保存先は./public/images) //Express4の仕様かなんかで画像staticなファイルを保存するときはpublic/以下のフォルダに置かないとダメらしい//詳しくは express.static public でググろう!destination:function(req,file,cb){cb(null,'./public/images/')},//ファイル名を指定//ここでは image.jpg という名前で保存filename:function(req,file,cb){cb(null,'image.jpg')}})varupload=multer({storage:storage})//*** 追加1 ここまで ***///* GET home page. */router.get('/',function(req,res,next){res.render('index',{title:'Express'});});//*** 追加2 ここから ***////ルート (/) に対する POST リクエスト//name タグにfileを指定したもののみ受け付けるrouter.post('/',upload.single('file'),function(req,res){res.render('image'); //*** 修正 ***//});//*** 追加2 ここまで ***//module.exports=router;
res.json({ 'result': 'success!' });
を
res.render('image');
にして、image.ejsを返すだけです。
5. Herokuにアップロードする
Herokuにアップロードするときはルートディレクトリ(testproject配下)にProcfileというファイルを作って中に
を記述して、git push heroku masterすればいいはず。
具体的なHerokuの登録とかアップロード方法はぐぐってくだされば・・・
僕はこの記事を参考にしました
以上、間違っていることとか定石から外れていることも多いかもしれないですが、動いたのでいいという気持ちです。なにかあれば気軽にコメントください。
疲れたので寝ます。。。
参考記事