画像を投稿してみよう - osamu38/node-express-curriculum GitHub Wiki
- 画像を投稿してみよう
- Cloudinaryを使ってサーバーに画像をアップしよう
画像を投稿するためには画像を一時的に保存するフォルダを作成する必要があります。なので/public/images/
にuploads
フォルダを作成しましょう。
$ mkdir -p ./public/images/uploads
フォームからファイルをアップロードするためのmodule、multerを導入しましょう。
$ npm install --save multer
メッセージと一緒に画像を投稿できるようにしたいので、Viewファイル側の準備をします。
views/board.js
を以下のように書き換えます。
<!-- 中略 -->
<form action="/boards/<%= board.board_id %>" method="post" enctype="multipart/form-data" class="board-form"> <!-- 変更 -->
<input type="text" name="message" class="input" required>
<button type="submit" class="submit">投稿</button>
<div class="file-wrap">
画像を追加
<input type="file" name="image_file" class="file">
</div>
</form>
<!-- 中略 -->
注目すべきポイントはformタグにenctype="multipart/form-data"
が設定されているところです。これを設定することでサーバー側でファイルを受け取ることができるようになります。
またinputタグのtype属性がfile
になっています。これはその名のとおりファイルをアップロードするための属性で、このinputタグをクリックするとファイルを選択するダイアログが表示されます。これを使ってアップロードするファイルを選択することができます。
では今の時点で詳細ページを見てみましょう。
デフォルトだとかっこ悪いのでボタンのデザインを変更しています。では次にファイルをアップロードするロジックを実装しましょう。
routes/boards.js
を以下のように書き換えます。
// 中略
var moment = require('moment');
var multer = require('multer'); // 追加
var connection = require('../mysqlConnection');
var upload = multer({ dest: './public/images/uploads/' }); // 追加
// 中略
// 中略
router.post('/:board_id', upload.single('image_file'), function(req, res) { // 変更
console.log(req.file); // 追加
var message = req.body.message;
// 中略
先ほど導入したmulter
を使用したいのでrequire('multer')
します。
そしてvar upload = multer({ dest: './public/images/uploads/' });
でアップロードされた画像の保管場所を設定しています。./public/images/uploads/
ですね。
最後にrouter.post('/:board_id', upload.single('image_file'), function(req, res) {
のupload.single('image_file')
に注目です。こいつの第一引数は先ほどinputタグに設定したname属性と同じ値を設定しています。
ちなみにreq.file
には投稿された画像の情報が入っています。
では画像を選択して投稿してみましょう。
今回はこのキツネの画像を選択!
ターミナルを見ると...
投稿された画像の情報が取得できていますね。
では実際に画像がアップロードされているかpublic/images/uploads/
を見てみましょう。
ちゃんと画像が追加されていますね。(ファイル名がおかしいですが、、、)
というわけで画像をアップロードすることはできましたが、ローカルに画像が保存されただけなのでこの画像を別のサーバーにあげてみたいと思います。
Cloudinaryは画像を保存するためのサーバーにみたいなイメージです。
ではさっそく利用してみましょう。
中央にあるSIGN UP FOR FREEを押してください。
このような会員登録の画面が表示されると思います。
(Optional)の部分を除いて記入が完了したらCREATE ACCOUNTを押してアカウントを作成しましょう。
アカウント作成後にダッシュボードを確認すると、
ここに書いてあるように[CLOUD_NAME]
や[API_KEY]
や[API_SECRET]
があると思います。この情報はCloudinaryに接続する際に使う設定なので覚えておきましょう。
そしてcloudinaryをnode側に導入しましょう。
$ npm install --save cloudinary
では次にデータベースに画像のパスを保存したいので修正しましょう。
カラム | 型 | 長さ | 符号ナシ | ゼロフィル | バイナリ | ヌル許可 | キー | デフォルト | 追加情報 |
---|---|---|---|---|---|---|---|---|---|
image_path | VARCHAR | 255 | false | false | false | false | None |
routes/boards.js
を以下のように書き換えます。
// 中略
var upload = multer({ dest: './public/images/uploads/' });
var cloudinary = require('cloudinary');
cloudinary.config({
cloud_name: '[CLOUD_NAME]',
api_key: '[API_KEY]',
api_secret: '[API_SECRET]'
});
// 中略
// 中略
var getBoardQuery = 'SELECT * FROM boards WHERE board_id = ' + boardId;
var getMessagesQuery = 'SELECT M.message, M.image_path, ifnull(U.user_name, \'名無し\') AS user_name, DATE_FORMAT(M.created_at, \'%Y年%m月%d日 %k時%i分%s秒\') AS created_at FROM messages M LEFT OUTER JOIN users U ON M.user_id = U.user_id WHERE M.board_id = ' + boardId + ' ORDER BY M.created_at ASC'; // 変更
connection.query(getBoardQuery, function(err, board) {
// 中略
// 中略
router.post('/:board_id', upload.single('image_file'), function(req, res) {
var path = req.file.path;
var message = req.body.message;
var boardId = req.params.board_id;
var userId = req.session.user_id? req.session.user_id: 0;
var createdAt = moment().format('YYYY-MM-DD HH:mm:ss');
cloudinary.uploader.upload(path, function(result) {
var imagePath = result.url;
var query = 'INSERT INTO messages (image_path, message, board_id, user_id, created_at) VALUES ("' + imagePath + '", ' + '"' + message + '", ' + '"' + boardId + '", ' + '"' + userId + '", ' + '"' + createdAt + '")';
connection.query(query, function(err, rows) {
res.redirect('/boards/' + boardId);
});
});
});
// 中略
views/boards.ejs
を以下のように書き換えます。
<!-- 中略 -->
<div class="message">
<% if (messageItem.image_path) { %>
<a href="<%= messageItem.image_path %>" class="message__image" style="background-image: url(<%= messageItem.image_path %>);"></a>
<% } %>
<p class="message__title"><%= messageItem.message %></p>
<!-- 中略 -->
ちゃんと画像が表示されていますね! では次にCloudinaryに画像が投稿されているかみてみましょう。
無事にキツネの画像が投稿されているのがわかると思います。 これで画像のアップロードは完了です。
前のページ:ユーザー情報を投稿に紐付けてみよう
次のページ:アプリケーションを公開しよう