创建页面
回顾技术方案
查看模板代码
- src-views-setting.ejs:
- 使用的是bootstrap的模板
开发页面路由
- 创建渲染“设置页”的路由:src-routes-view-user.js中,注意需要先使用“登录验证中间件”,如果用户未登录则带着当前url(
/setting
)跳转到登录页,登录后自动跳转回“设置页”:
开发接口
图片上传(文件上传)
回顾技术方案
formidable-upload-koa工具(文件上传)
- koa要图片(文件)上传就要借助formidable-upload-koa工具
- 安装:
npm i formidable-upload-koa
- 使用:
- 由于该中间件会将图片(文件)保存在本机或服务器的一个临时文件夹中,所以我们需要fse工具将其改成存储在我们指定的文件夹
- options:配置,不写则使用默认配置
- uploadDir:图片保存目录
- keepExtensions:是否保留文件扩展名
fs-extra工具(文件操作)
- 涉及文件操作就要使用fs-extra工具
1
2
3
4
5
6
7
8
9
10const fse = require('fs-extra')
//删除filePath路径的文件
await fse.remove(filePath)
//将filePath路径的文件移动到distFilePath路径
await fse.move(filePath, distFilePath)
//判断文件夹是否存在,DIST_FOLDER_PATH为文件夹路径
fse.pathExists(DIST_FOLDER_PATH)
//新建文件夹,在DIST_FOLDER_PATH路径下新建文件夹
fse.ensureDir(DIST_FOLDER_PATH)
步骤
- 安装formidable-upload-koa工具、fs-extra工具:
npm i formidable-upload-koa fs-extra --save
- 【路由层】创建上传图片的路由,使用formidable-upload-koa工具创建中间件将图片文件上传到服务器/本机的某个临时文件夹中:在前端页面中,用户通过调用/api/utils/upload上传图片,所以在src-routes-api下新建utils.js:
- 修改个人头像和上传微博时都需要上传图片,所以将上传图片的路由抽离到utils.js中,方便复用
- 引入formidable-upload-koa工具的koaForm函数创建中间件
- 前端上传文件的ajax方法(my-ajax.js)中文件保存在FormData對象的file值中:这个file就对应后端的src-routes-api-utils.js中
ctx.req.files['file']
的file,要修改的话两边要一起改。FormData 对象的使用、FormData使用方法详解
- 【controller层】限定文件大小、移动文件存储的位置:在路由层使用formidable-upload-koa工具的中间件时就已经将文件上传至某个临时文件夹,所以现在我们可以将文件移动到我们指定的位置。controller下新建util.js:为啥distFilePath中包含文件名: 查看通过formidable-upload-koa工具保存的文件路径可看到是包括到随机生成的文件名的(
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51/**
* @description utils controller
* @author hlz
*/
const path = require('path')
const { ErrorModel, SuccessModel } = require('../model/ResModel')
const { uploadFileSizeFailInfo } = require('../model/ErrorInfo')
const fse = require('fs-extra')
// 存储目录
const DIST_FOLDER_PATH = path.join(__dirname, '..', '..', 'uploadFiles')
// 文件最大体积 1M
const MIX_SIZE = 1024 * 1024 * 1024
// 是否需要创建目录
fse.pathExists(DIST_FOLDER_PATH).then(exist => {
if (!exist) {
fse.ensureDir(DIST_FOLDER_PATH)
}
})
/**
* 保存文件
* @param {string} name 文件名
* @param {string} type 文件类型
* @param {number} size 文件体积大小
* @param {string} filePath 文件路径
*/
async function saveFile({ name, type, size, filePath }) {
// 文件过大时
if (size > MIX_SIZE) {
// 使用fs-extra工具删除文件(以防占用硬盘空间)
await fse.remove(filePath)
return new ErrorModel(uploadFileSizeFailInfo)
}
// 移动文件(从filePath到distFilePath)
const fileName = Date.now() + '.' + name // 防止重名
const distFilePath = path.join(DIST_FOLDER_PATH, fileName) // 目的地
await fse.move(filePath, distFilePath)
// 返回信息
return new SuccessModel({
url: '/' + fileName
})
}
module.exports = {
saveFile
}upload _xxx
),这个路径是直接可以访问到图片的路径,所以移动的目的路径中也要包含文件名 - 新建uploadFiles文件夹并先保存一张图片2.png
- 【保证controller-util.js中saveFile返回的url可被访问到】:将uploadFiles文件夹设置为静态目录的文件夹=》什么东西放里面都可被访问=》保证controller-util.js中saveFile返回的url可被访问到。app.js中进行设置:设置后,我们可通过访问http://localhost:3000/2.png访问到uploadFiles文件夹下的图片2.png
- 【app.js注册路由】:
- 测试:http://localhost:3000/setting![测试](https://i0.wp.com/ww1.sinaimg.cn/large/005H7IVsgy1gdx1b9n6tzj31050i2jtk.jpg)
- 后端筛选文件格式:controller-util.js:
- 测试:尝试上传css后缀的文件:
- 前端筛选文件格式:accept 属性只能与
<input type="file">
配合使用,它规定能够通过文件上传进行提交的文件类型。**image/*
表示接受所有的图像文件。** - 前端限定后再选择文件时直接就不给选择css后缀的文件了。
补充:线上图片存储
- 我们现在是把图片存储在本地的uploadFiles文件夹中,但实际上线时应使用专业的文件服务(比如七牛云等)来保存图片文件,它再返回图片url供程序使用:
修改基本信息
- 【路由层】创建路由,传递前端数据,调用controller层函数:前端setting.ejs中修改基本信息的路由是**/api/user/changeInfo,传递的前端数据是
nickName,city,picture
,所以在routes-api-user.js中创建changeInfo路由,将前端获取的数据传递并调用controller层的changeInfo函数**:(新建用post,修改用patch) - 【controller层】创建changeInfo函数,调用service层函数更新数据库数据,修改session.userInfo:src-controller-user.js:
- Object.assign()合并对象,当合并的多个对象拥有相同属性时后面的属性值覆盖前面的。
- 【service层】创建更新数据库中users表(User模型)的方法:src-service-user.js:
- updateData和whereData的属性名需要和de-model-User.js中User模型的属性名对应
- 测试:数据库的users表:此时无论怎么刷新页面,都会显示已修改的信息:
修改密码
- 【路由层】创建路由,传递前端数据,调用controller层函数:前端setting.ejs中修改密码的路由是**/api/user/changePassword,传递的前端数据是
password、newPassword
,所以在routes-api-user.js中创建changePassword路由,将前端获取的数据传递并调用controller层的changePassword函数**: - 【controller层】创建changePassword函数,调用service层函数更新数据库数据,修改session.userInfo:src-controller-user.js:
- 【service层】还是和修改个人信息一样的方法来更新数据库中users表(User模型)的方法
- 测试:
退出登录
- 【路由层】创建路由,调用controller层函数:前端setting.ejs中退出登录的路由是**/api/user/logout,所以在routes-api-user.js中创建logout路由,调用controller层的logout函数**:
- 【controller层】创建logout函数,删除session.userInfo:src-controller-user.js中,我们判断登录状态时使用的是session.userInfo,删除它自然就退出登录了:
delete
关键词可用于删除ctx.session
- 测试: