[Express] Express 起步走 Getting Started
Express
設定靜態路徑:express.static
// app.js
app.use('/upload', express.static(`${__dirname}/upload`));
Response
res.locals
僅作用於該 request - response 的物件,因此只能在該 request-response 所轉譯的頁面取得,除此之外它和 app.locals
是一樣的。適合用在使用者 資訊的設定、驗證等。
// controller
app.use(function (req, res, next) {
res.locals.user = req.user;
res.locals.authenticated = !req.user.anonymous;
next();
});
可以直接在 View 的地方取得 user
和 authenticated
的值。
res.redirect
res.redirect() @ Express API
// 回到上一層路徑
// 例如,http://example.com/admin/post/new,則會回到 http://example.com/admin/post
res.redirect('..');
// 回到 referer 的網址,若沒有提供,則會回到 '/'
res.redirect('back');
常用工具
express-handlebars
const exphbs = require('express-handlebars');
app.engine('hbs', exphbs({ defaultLayout: 'main', extname: '.hbs' }));
app.set('view engine', 'hbs');
解析 body-parser, urlencoded, json
var express = require('express');
var app = express();
app.use(express.json()); // for parsing application/json
app.use(express.urlencoded({ extended: true })); // for parsing application/x-www-form-urlencoded
app.post('/profile', function (req, res, next) {
console.log(req.body);
res.json(req.body);
});
使用 session:express-session
const session = require('express-session');
app.use(
session({
secret: 'secret',
resave: false,
saveUninitialized: false,
}),
);
使用 flash 提示訊息:connect-flash
// app.js
const flash = require('connect-flash');
const app = express();
app.use(express.session({ cookie: { maxAge: 60000 } }));
app.use(flash());
// STEP 1:把 flash 的值存到 locals
app.use((req, res, next) => {
res.locals.success_messages = req.flash('success_messages');
res.locals.error_messages = req.flash('error_messages');
next();
});
// controller
// STEP 2:在 controllers 中有需要時帶入 flash 訊息
app.get((res, res, next) => {
req.flash('success_message', 'some success messages');
});
使用 GET 和 PUT 以外的 HTTP 方法:method-override
Controller
// app.js
const methodOverride = require('method-override');
app.use(methodOverride('_method'));
Routes
app.put('/restaurants/:restaurantId', (req, res) => {
/* ... */
});
app.delete('/restaurants/:restaurantId', (req, res) => {
/* ... */
});
<!-- form.html -->
<form action="/restaurants/{{restaurant.id}}?_method=PUT" method="POST">
<!-- ... -->
</form>
<form
action="/restaurants/{{this.id}}?_method=DELETE"
method="POST"
style="display: inline;"
>
<!-- ... -->
</form>
上傳圖片:multer
未來考慮使用 formidable @ npmjs
View
加上 enctype="multipart/form-data"
<form
action="/admin/restaurants/{{restaurant.id}}?_method=PUT"
method="POST"
enctype="multipart/form-data"
>
<div class="form-group">
<label for="image">Image</label>
<input type="file" class="form-control-file" name="image" id="image" />
</div>
</form>
Routes
使用 upload.single('image')
表示上傳一張圖片:
// routes
const multer = require('multer');
const upload = multer({ dest: 'temp/ ' }); // 把上傳的暫存檔存放到 temp 資料夾
// multer 只要看到 request 內有圖片,就會自動複製到 temp 資料夾
app.post('/admin/restaurants/', upload.single('image'), (req, res) => {
/* ... */
});
Controller
// Controller
const putRestaurant = async (req, res) => {
const { restaurantId } = req.params;
const { file } = req;
const { path, originalname } = file;
try {
if (file) {
const data = await fs.promises.readFile(path);
await fs.promises.writeFile(`upload/${originalname}`, data);
}
const restaurant = await Restaurant.findByPk(restaurantId);
await restaurant.update({
image: file ? `/upload/${originalname}` : restaurant.image,
});
req.flash('success_messages', '成功上傳圖片');
return res.redirect('/admin/restaurants');
} catch (error) {
req.flash('error_messages', `上傳圖片失敗(${error})`);
return res.redirect('/admin/restaurants/edit');
}
};
File 物件
// req.file
{
fieldname: 'image',
originalname: '1.jpeg',
encoding: '7bit',
mimetype: 'image/jpeg',
destination: 'temp/ ',
filename: '07b52fd0891d5a870bc885ed51ea060e',
path: 'temp/ /07b52fd0891d5a870bc885ed51ea060e',
size: 11245
}