创建项目
运行命令
cnpm i egg-init -gegg-init egg01 --type=simplecd egg01cnpm installnpm run dev复制代码
终端效果
配置路由,模板,数据库,中间件
路由
app\router.js
router.get('/', controller.user.index); router.get('/add', controller.user.add); router.get('/edit', controller.user.edit); router.post('/doAdd', controller.user.doAdd);复制代码
模板
安装依赖egg-view-ejs
cnpm install egg-view-ejs --save复制代码
配置模板
config\plugin.js
exports.ejs = { enable: true, package: 'egg-view-ejs',};复制代码
config\config.default.js
config.view = { mapping: { '.html': 'ejs', }, };复制代码
配置数据库
安装依赖egg-mongoose
cnpm install egg-mongoose --save复制代码
配置数据库
config\plugin.js
exports.mongoose = { enable: true, package: 'egg-mongoose',};复制代码
config\config.default.js
config.mongoose = { client: { url: 'mongodb://egg01:123456@127.0.0.1/egg01', options: {}, }, };复制代码
数据库映射
app\model\user.js
module.exports = app => { const mongoose = app.mongoose; const Schema = mongoose.Schema; const UserSchema = new Schema({ username: { type: String, }, password: { type: String, }, avator: { type: String, }, }); return mongoose.model('User', UserSchema, 'user');};复制代码
中间件csrf
安全验证
app\middleware\auth.js
module.exports = (options, app) => { return async function auth(ctx, next) { ctx.state.csrf = ctx.csrf; await next(); };};复制代码
config\config.default.js
config.middleware = [ 'auth' ];复制代码
单文件上传
缺陷
图片必须放在表单的最后面,并且图片可能会丢失
view
代码
app\view\user\add.html
复制代码Document csrf: <%= csrf %>
效果
controller
app\controller\user.js
'use strict';const Controller = require('egg').Controller;const fs = require('fs');const path = require('path');const pump = require('mz-modules/pump');class HomeController extends Controller { async add() { await this.ctx.render('user/add'); } async doAdd() { const stream = await this.ctx.getFileStream(); // 获取表单提交的数据 if (!stream.filename) { // 注意如果没有传入图片直接返回 return; } // 图片上传到静态文件夹 let target = 'app/public/upload/' + path.basename(stream.filename); // "filename":"c:/images/291051166-5b20eca6448e8_articlex.png", path.basename => 291051166-5b20eca6448e8_articlex.png const writeStream = fs.createWriteStream(target); await pump(stream, writeStream); // stream.pipe(writeStream); //可以用, 但是不建议,因为不能处理失败的情况 // 存入数据库 target = target.slice(3); const newUser = Object.assign(stream.fields, { avator: target, }); await this.ctx.service.user.doAdd(newUser); // 跳转 this.ctx.redirect('/'); }}module.exports = HomeController;复制代码
service
app\service\user.js
'use strict';const Service = require('egg').Service;class UserService extends Service { async doAdd(user) { const newUser = new this.ctx.model.User(user); newUser.save(); }}module.exports = UserService;复制代码
上传效果
表单
上传后返回给前端
存储到项目后台静态文件夹
多文件上传
view
把上传按钮悠为<input type="file" multiple="multiple" name="avator">
,文件上传变为多选
复制代码Document csrf: <%= csrf %>
controller
async doAdd() { // { autoFields: true }:可以将除了文件的其它字段提取到 parts 的 filed 中 // 多个图片/文件 const parts = this.ctx.multipart({ autoFields: true, }); const files = []; let stream; while ((stream = await parts()) != null) { if (!stream.filename) { // 注意如果没有传入图片直接返回 return; } const fieldname = stream.fieldname; // file表单的名字 face const target = 'app/public/upload/' + path.basename(stream.filename); const writeStream = fs.createWriteStream(target); await pump(stream, writeStream); // 写入并销毁当前流 (egg demo提供的) files.push({ [fieldname]: target, // es6里面的属性名表达式 }); } const avator = files[0].avator.slice(3); //只选第一张图片 const newUser = Object.assign(parts.field, { avator, }); await this.ctx.service.user.doAdd(newUser); // 跳转 this.ctx.redirect('/'); }复制代码