基于Vue3+koa2+mongoose的图片上传功能实现
前言
大家好,我是其润丿。最近在做毕设的过程中,遇到了图片上传的功能。在查阅了很多资料后,发现大多数都是只有前端部分而缺少后端部分。所以这篇文章我将用保姆级的教程来具体讲解图片上传功能前端和后端的代码功能实现。
前端部分
所用技术栈描述
因为我的整体项目技术栈使用的是vue3,所以在前端的图片上传功能部分,使用了element-plus中的el-upload组件进行实现。具体使用文档:el-upload。如果大家的项目使用的是react进行完成的,同理可以使用Ant Design中的Upload组件进行实现。具体使用文档: Upload。实现方法都大同小异,很多具体的使用详情可以通过查阅文档进行了解。 下面我将根据element-plus中的写法进行讲解。
功能具体实现
<el-upload
class="avatar-uploader"
action="/api/files/upload"
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
>
<img v-if="flowerForm.src" :src="flowerForm.src" class="avatar" />
<el-icon v-else class="avatar-uploader-icon"><Plus /></el-icon>
</el-upload>
具体使用的el-plus的api讲解
- action是我们要向后端调用的后端的接口地址,即我们通过这个地址可以将图片传到数据库中。因为这里我是直接按照file文件的方法进行传递的。如果有小伙伴想通过base64转码的方式进行传递,那么将action置空即可。再在上传前函数中进行base64转码的操作就可以,这里我就不继续啰嗦了。
- show-file-list是是否显示已上传文件列表,默认为true,这里我们将其设置为false
- on-success是文件上传成功时的钩子,我们可以将返回过来的参数/url链接向我们项目中对应的参数进行赋值,在后面我将把这个函数具体实现方法展示出来。
- before-upload是上传文件之前的钩子,参数为上传的文件, 若返回
false
或者返回Promise
且被 reject,则停止上传。我们可以在这个函数中对我们上传图片的格式与大小进行限制。同样的在后面我将把这个函数具体实现方法展示出来。 - img则为图片上传后的展示,src即为我们图片返回回来后被赋值的参数
- el-icon是图片未上传之前,我们展示的+的样式图标。Plus同样为element-plus中的图标。所有图标库
上传文件之前函数的具体写法
// 图片上传前的判断
const beforeAvatarUpload = (file) => {
//对上传图片格式的限制
let types = ['image/jpeg','image/gif','image/bmp','image/png']
const isImage = types.includes(file.type)
//对上传图片大小的限制
const isLt1M = file.size / 1024 / 1024
if(!isImage){
ElMessage.error('上传图片只能是JPG/Jpeg/GIF/BMP/PNG格式!')
return false
}
if (isLt1M > 2) {
ElMessage.error('上传头像图片大小不能超过2MB')
return false
}
return true
}
- 从函数的备注中我们可以看到,我限制了上传图片的格式以及大小,只要是不符合要求的都会返回
false
,这样的话图片上传就会终止,否则才会继续进行。 - 提示信息的话我调用的同样是element-plus中的ElMessage方法。具体文档:Message消息提示
文件上传成功函数的具体写法
// 图片成功上传的函数
const handleAvatarSuccess = (response,uploadFile) => {
// flowerForm.src = URL.createObjectURL(uploadFile.raw)
flowerForm.src = response.filename
}
- 这里可以看到我注释掉了一行代码。其实对应的是调用两种形参的两种写法
- 可以看到我是直接调用的response,因为我在后端接口代码中直接将图片对应的url返回了回来,这样的话我们就可以通过response获取到对应的url直接进行赋值,会在后续后端代码中进行具体体现。
- 而如果我们在后端代码中没有直接将图片对应的url返回回来,而是只返回了对应的参数。那么就可以使用我注释掉的那行写法,通过URL.createObjectURL() 对参数进行url转换。同样可以获取到url对参数进行赋值。
后端部分
所用中间件描述
首先需要下载koa-multer
这个基于node.js的中间件,用于处理 multipart/form-data
类型的表单数据,它主要用于上传文件。其次是创建图片上传的接口的前提,我们需要通过koa-static
和path
进行托管静态资源。下面我将对其一一进行详细讲解
托管静态资源
目录结构
- 首先我们需要创建一个文件夹来进行静态资源托管,这里我创建的是public文件夹
- 然后在app.js也就是根目录中来编写我们托管静态资源的代码。
导入static和path第三方模块
// 引入托管静态资源
const static = require('koa-static')
const path = require('path')
// 使用static托管静态资源
app.use(static(path.join(__dirname,'/public')))
- 首先我们需要npm i koa-static来进行下载(node自带path不用下载)
- 然后通过app.use() 对我们的中间件进行使用
- 注意所指向的文件夹的地址一定要正确
验证托管是否成功
- public目录下随便放个图片
- 通过你的node的服务器地址加上图片名称,在浏览器输入访问,有画面就是托管成功
- 如果你的图片放在public里面的文件夹中,地址上的端口号后面应该加上这个文件夹的名字
- 托管成功后,访问资源的地址可以省略public,但是public里面的不可省略
实现接口功能
配置koa-multer
下载koa-multer
npm i koa-multer
具体配置
// 引入配置koa-multer模块(用来处理图片上传)
const multer = require('koa-multer')
const path = require('path')
// 进行multer配置
let storage = multer.diskStorage({
//文件保存路径
destination: function (req, file, cb) {
cb(null, path.join(__dirname ,'../../public/uploads')) //路径一定要对
},
// 修改文件名称
filename: function (req, file, cb) {
let fileFormat = (file.originalname).split(".");
cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
})
//加载配置
let upload = multer({ storage: storage })
- destination是文件保存的路径,我在pulic下创建了一个新的文件夹叫uploads,用来接收上传的图片,这里的路径一定要写对
- filename是修改上传图片的名称,通过split对图片的名称进行切割,获取图片的后缀格式。然后通过使用Date.now()创建的时间戳+图片的后缀进行拼接从而形成新的名称,来保证名称的唯一性
- 我们可以将koa-multer的配置放在一个单独的文件夹中,通过module.exports = upload进行导出,具体使用的部分再进行引入。因为我只有这个接口中需要用到此配置,所以我这里的话就是和下面的接口写在了一个页面中,就不需要再重新引入了。
接口实现
const Router = require('koa-router')
// 创建router
const filesRouter = new Router()
/**
* @route POST api/files/upload
* @description 上传图片
* @access 接口公开
*/
filesRouter.post('/upload',upload.single('file'),async (ctx) =>{
// 图片地址拼接
const headPath = 'http://localhost:5000/uploads/' + ctx.req.file.filename
ctx.body = {
filename: headPath,//返回文件名
body:ctx.req.body,
status:200,
success:true,
}
})
module.exports = filesRouter
- upload.single('file') 是我们调用multer的配置,并且要求传过来的图片字段为file
- ctx.req.file.filename 是我们对图片修改后的名称
http://localhost:5000/uploads/
是我们之前通过设置托管静态资源可以直接调用的地址,可以看到public字段被省略掉了,但是uploads文件夹并没有被省略- 根据
http://localhost:5000/uploads/
+ ctx.req.file.filename,进行拼接就是我们向前端直接返回的url,就和我前面的前端写法一样。可以直接获取后端返回的参数从而进行赋值、 - 提示:
http://localhost:5000/
,5000的原因是因为我的后端项目中自己设置的端口号为5000,大家自己可以定义不同的端口号
将两者整合进行整体展示
const Router = require('koa-router')
// 引入配置koa-multer模块(用来处理图片上传)
const multer = require('koa-multer')
const path = require('path')
// 创建router
const filesRouter = new Router()
// 进行multer配置
let storage = multer.diskStorage({
//文件保存路径
destination: function (req, file, cb) {
cb(null, path.join(__dirname ,'../../public/uploads')) //路径一定要对
},
// 修改文件名称
filename: function (req, file, cb) {
let fileFormat = (file.originalname).split(".");
cb(null,Date.now() + "." + fileFormat[fileFormat.length - 1]);
}
})
//加载配置
let upload = multer({ storage: storage })
/**
* @route POST api/files/upload
* @description 上传图片
* @access 接口公开
*/
filesRouter.post('/upload',upload.single('file'),async (ctx) =>{
// 图片地址拼接
const headPath = 'http://localhost:5000/uploads/' + ctx.req.file.filename
ctx.body = {
filename: headPath,//返回文件名
body:ctx.req.body,
status:200,
success:true,
}
})
module.exports = filesRouter
效果展示
这里的话,大家可以使用postman对接口进行测试。我就直接使用我做好的毕设来进行前端和后端效果的同时展示了。
此时我们对返回的url进行复制,在新的页面打开这个地址
可以看到此地址就是对图片的展示,到此我们的效果展示完成。前端后端功能实现完成。
结尾
图片上传功能是我在做毕设的过程中遇到的具体功能,在实现过程中遇到了一些问题。想到了大家可能也会有和我一样的问题,于是写下了这篇文章来供大家学习。希望能帮助到大家的学习,如果文章中出现了一些错误也欢迎大家指出,不足之处也大家请多多包涵与谅解。
转载自:https://juejin.cn/post/7209917117470605368