Appearance
编写使用案例
编写todo 案例
在开始案例之前需要了解一个库 lowdb ,在网站开发时候我们需要将数据进行一些存储可以选择使用关系型数据库(如 MySQL)或非关系型数据库(如 MongoDB)。但是,在一些小规模的项目中,使用一个完整的数据库可能过于笨重。
在这种情况下,可以使用 lowdb 是一个基于 JavaScript 的轻量级的本地 JSON 数据库,它的特点主要是方便易用和可嵌入性,让你可以更加自由的开发自己的业务。它使用了 lodash 的一些高级 API 来实现,所以它非常小而且快速;平均启动时间0.8 ms。它的 API 设计十分简单,最基本的增删查改等操作都是十分便捷,而且你可以把它应用到各种不同的项目中,比如构建网站、应用程序和桌面软件等。
此外,lowdb 的实现方式与传统数据库完全不同,它的数据存储方式为一个 JSON 文件,这样可以避免一些过多的配置和管理问题,不需要为了使用这个库而去管理一个成熟的数据库环境。使用 lowdb 可以让你更加专注于你的业务逻辑,而不是去研究复杂的数据库管理问题。总之,如果你想要一个非常简单易用的本地 JSON 数据库
为了使用cjs 版本 这里安装的是1.0版本
shell
npm i lowdb@1.0.0
使用案例,每次启动
js
//导入 lowdb
const low = require('lowdb')
const FileSync = require('lowdb/adapters/FileSync')
const adapter = new FileSync('db.json');
//获取 db 对象
const db = low(adapter);
//初始化数据
// db.defaults({ posts: [], user: {} }).write()
//写入数据
// db.get('posts').push({id: 2, title: '今天天气还不错~~'}).write();
// db.get('posts').unshift({id: 3, title: '今天天气还不错~~'}).write();
//获取单条数据
// let res = db.get('posts').find({id: 1}).value();
// console.log(res);
//获取数据
// console.log(db.get('posts').value());
//删除数据
// let res = db.get('posts').remove({id: 2}).write();
// console.log(res);
//更新数据
// db.get('posts').find({id: 1}).assign({title: '今天下雨啦!!!'}).write()
上传中间件
上传中间件选择是 multer ,在上传时候一般使用格式是multipart/form-data
,为了可以处理此时就需要 multer , 可以通过 req.body
获取普通表单字段,上传文件需要根据对应 req.file
进行获取
基本使用上有两种模式 暂时保存在内存中 和 直接保存在本地磁盘里,具体使用可以参考文档,但要注意的是获取的文件名称是中文可能会乱码,需要使用 Buffer.from(file.originalname, 'latin1').toString('utf8')
去转码
在 案例中使用的代码位置是 routes/todo.js 中,可以看到在导入 require('multer')
后去定义了使用了 multer.diskStorage
将上传文件保存在了磁盘中,提供了 destination
和 filename
通过提供的回调函数进行格式上的修改,默认上multer 特殊性质导致名字生成 不会为你添加任何扩展名,所以会在 filename
去定义我们实际保存的名字,multer 也提供了 fileFilter
这个字段可以帮助进行一些类型判断, 将错误抛出异常
js
var express = require('express')
var router = express.Router()
const path = require('path')
const shortid = require('shortid')
// 确保你总是处理了用户的文件上传。 永远不要将 multer 作为全局中间件使用,
// 因为恶意用户可以上传文件到一个你没有预料到的路由,应该只在你需要处理上传文件的路由上使用。
const multer = require('multer')
// 保存在磁盘上
const storage = multer.diskStorage({
// 设置保存位置路径
// destination: '/upload',
destination(req, file, cb) {
cb(null, './uploads')
},
// 设置项目名称
filename(req, file, cb) {
// 由于multer 特殊性质导致名字生成 不会为你添加任何扩展名,会自动把文件的后缀名删除并添加一个随机的扩展名,这是为了防止文件名重复和安全问题
// 我要自动拼接文件名 时间戳 + 文件名
const prefix = Date.now()
// 参考 https://github.com/expressjs/multer/issues/1104 解决文件上传乱码问题
const fileName = path.basename(
Buffer.from(file.originalname, 'latin1').toString('utf8')
)
cb(null, `${prefix}-${fileName}`)
// const extension = path.extname(originalname)
// const basename = path.basename(originalname, extension) // 不包括扩展名只包含文件名
// const encodedName = encodeURIComponent(basename)
// const newFilename = `${encodedName}-${Date.now()}${extension}`
},
})
const upload = multer({
storage,
limits: { fileSize: 2 * 1024 * 1024 },
fileFilter(req, file, cb) {
// 过滤文件类型
const fileType = file.mimetype.toLowerCase()
if (
fileType === 'image/png' ||
fileType === 'image/jpg' ||
fileType === 'image/jpeg' ||
fileType === 'image/webp'
) {
cb(null, true)
} else {
cb(new Error({ code: 'FILE_TYPE' }), false)
}
},
})
// 新增: 增加个人任务 在html页面时候 图片对应字段为file 作为前端传过来的key
router.post(
'/add',
upload.single('file'),
(req, res) => {
// req.file 是 `avatar` 文件的信息
// req.body 将具有文本域数据,如果存在的话
// 逻辑将数据保存到dblow 上, 可以参考https://github.com/hua1995116/webchat/blob/d3f37273bff43b297148846c5122384d618149fc/router/files.js#L41
console.log(req.file, 111111111)
// 只要是上传不符合要求的文件,cb(123, false) 此时就没有req.file
// if (!req.file) {
// res.json({ msg: '文件错误' })
// return
// }
let imgPath = ''
let id = shortid.generate()
if (req.file) {
// 保存图片路径
imgPath = path.normalize(req.file.path)
}
req.db
.get('todos')
.push({ id, ...req.body, imgPath })
.write()
res.json({ msg: '新增成功', code: 200 })
},
(err, req, res, next) => {
// 为精确的错误处理,你可以使用 instance 来确定 MulterError 是不是你想要的错误类型。
if (err.code === 'LIMIT_FILE_SIZE') {
// limits 错误会进入 multer.MulterError 收集
res.json({ msg: '文件过大', code: 500 })
} else if (err.code === 'FILE_TYPE') {
res.json({ msg: '文件类型不符合要求', code: 500 })
}
next(err)
}
)