前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~

前后端分离 – 深入浅出系列 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~ 引言

Hello,我是Bug终结者,一名热爱后端Java的风趣且幽默的程序员~ 终于等到幸运的你~
快来发现我的宇宙哦~
博文系列 深入浅出前后端分离系列第一篇:前后端分离 — 深入浅出Spring Boot + Vue实现员工管理系统 Vue如此简单~
项目简介 开发一个基于Spring Boot + Vue的前后端分离相册管理系统项目,完成增、删、改、列表、多条件、分页的功能
功能细节:
  • 实现照片的新增、删除、修改、列表、多条件、分页
  • 图片上传使用 el-upload 控件,建议设置 auto-upload 为 false。
  • 控制图片最大不能超过5M
  • 上传的必须是图片,或者约束后缀为 png/jpg/gif/bmp等图片。
  • 建议先保存标题信息到数据库,并返回得到noid的值,然后再上传图片,并更新 relative_path字段。
  • 图片保存文件命名为 yyyyMMdd/HHmmssXXXX.后缀这样的图片,例如图片为 仓鼠.png,保存后类似为 20220107/1115232832.png, XXXX表示4位的随机数字。
  • 图片在列表上显示为 200X200大小
  • 列表要支持分页,分页控件使用 el-pagination
  • 删除的时候,要将图片从硬盘上删除掉,然后再删除数据库中的记录。
  • 列表页显示如下
    前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
    文章图片
效果图
开发环境 后端:Spring Boot + MyBatis + Maven
前端:Vue + ElementUI
工具:前端使用WebStorm,后端使用IDEA
放松一下~
前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

适度适度~
前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

挺解乏的哦~
言归正传~
项目风格 请求方式统一为Post请求,目的是保证安全性
规范了接口层统一返回格式为ResultBean,详细如:
统一返回格式风格类,ResultBean
状态码,详细信息,数据
数据表 t_picture
CREATE TABLE `t_picture` ( `noid` int(11) NOT NULL AUTO_INCREMENT, `picture_name` varchar(64) NOT NULL COMMENT '照片名称', `relative_path` varchar(128) DEFAULT NULL COMMENT '存储相对路径', `create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间', PRIMARY KEY (`noid`) ) ENGINE=InnoDB AUTO_INCREMENT=71 DEFAULT CHARSET=utf8mb4

项目结构 前端结构 前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

后端结构 前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

项目难点 前端部分难点:
上传文件采用elementui控件的el-upload,要求不可自动上传,所以设置自动上传为false 其中,要先保存数据到数据库在进行保存图片路径存入数据库,通过存入的数据id去修改当前的数据
显示图片时采用了provide / inject组合控制的显示 因为上传成功后需要再次刷新,如果不刷新,图片不出来,那就要重新刷新页面,但刷新页面对用户来说极不友好,而且时间慢,效率低,所以采用该显示方式,完美解决了二次加载的问题
介绍provide / inject组合控制的显示到底怎么用 首先在app.vue中加入如下代码
app.vue
@import '//at.alicdn.com/t/font_2048717_67mh6lqgbh.css';

在要二次加载的vue文件中加入provide
前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

执行完上传图片代码后,进行二次加载
前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

完美解决二次加载
核心源码 前端源码 PictureList.vue
.box-main2 { width: 90%; margin: 10px; box-table2{ height: auto; } .box-search{ display: flex; margin: 10px; .m1{ padding-left: 10px; } } .box-page1{ margin-top: 10px; } }

添加路由 route.js
{ path: '/picture-list', meta: {pageTitle: '相册管理', leftMenuIndex: 'picture-list'}, component: () => import('@/views/PictureList') },

添加左侧菜单显示 LeftMenu.vue
相册列表

后端源码 PictureController
package com.wanshi.controller; import com.github.pagehelper.PageInfo; import com.wanshi.bean.Picture; import com.wanshi.bean.ResultBean; import com.wanshi.service.PictureService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; import java.util.List; import java.util.Map; @RestController @CrossOrigin @RequestMapping("/picture") public class PictureController {@Autowired private PictureService pictureService; /** * 相册分页 * @param param * @return */ @PostMapping("/page") public ResultBean> page(@RequestBody Picture param) { ResultBean> res = pictureService.page(param); return res; }/** * 保存,将新增和修改合成了一个方法,根据id判断是新增或修改 * @param param * @return */ @PostMapping("/save") public ResultBean insert(@RequestBody Picture param) { ResultBean res = pictureService.save(param); return res; }/** * 删除图片 * @param param * @return */ @PostMapping("/delete") public ResultBean delete(@RequestBody Picture param) { ResultBean res = pictureService.delete(param); return res; }/** * 上传图片,与上传信息分开,改为手动上传,点击确定后,先保存数据,再保存图片相关信息至数据库 * @param map * @param file * @return */ @PostMapping("/upload") public ResultBean upload(@RequestParam Map map, MultipartFile file) { ResultBean res = pictureService.upload(map, file); return res; }}

PictureService
package com.wanshi.service; import com.github.pagehelper.PageHelper; import com.github.pagehelper.PageInfo; import com.wanshi.bean.Picture; import com.wanshi.bean.ResultBean; import com.wanshi.config.GlobalSet; import com.wanshi.mapper.PictureMapper; import com.wanshi.utils.PbFileUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.text.SimpleDateFormat; import java.util.List; import java.util.Map; @Service public class PictureService {@Autowired private GlobalSet globalSet; @Autowired private PictureMapper pictureMapper; private SimpleDateFormat sdf = new SimpleDateFormat("yyyy年MM月dd日"); public ResultBean> page(Picture param) { PageHelper.clearPage(); PageHelper.startPage(param.getPageNum(), param.getPageSize()); List pictureList = pictureMapper.list(param); for (Picture picture : pictureList) { if (picture != null) { picture.setStrCreateTime(sdf.format(picture.getCreate_time())); } } PageInfo pageInfo = new PageInfo<>(pictureList); return ResultBean.create(0, "success", pageInfo); }public ResultBean save(Picture param) { if (param.getNoid() != null ) { pictureMapper.update(param); } else { pictureMapper.insert(param); } return ResultBean.create(0, "success", param.getNoid()); }public ResultBean delete(Picture param) { //获取要删除的照片存储相对地址 Picture picture = pictureMapper.get(param); //拼接绝对路径并删除 new File(globalSet.getUploadPath() + picture.getRelative_path()).delete(); pictureMapper.delete(param); return ResultBean.create(0, "success", null); }public ResultBean upload(Map map, MultipartFile file) { try { //查询当前id是否存在,并上传过图片 Picture picture2 = new Picture(); picture2.setNoid(Integer.valueOf((String)map.get("noid"))); Picture picture3 = pictureMapper.get(picture2); if (picture3.getRelative_path() != null) { //拼接绝对路径并删除 new File(globalSet.getUploadPath() + picture3.getRelative_path()).delete(); } //上传文件,获得上传后的文件名称 String uploadName = PbFileUtils.upload(file, globalSet.getUploadPath()); if (!StringUtils.isEmpty((String)map.get("noid"))) { Picture picture = new Picture(); picture.setNoid((Integer.valueOf((String) map.get("noid")))); picture.setRelative_path(uploadName); pictureMapper.updateImg(picture); } } catch (Exception e) { e.printStackTrace(); } return ResultBean.create(0, "success", null); } }

工具类PbFileUtils
package com.wanshi.utils; import com.wanshi.config.GlobalSet; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; import org.springframework.web.multipart.MultipartFile; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Random; /** * 图片上传类 */ public class PbFileUtils {/** * 文件上传, * @param file 上传文件 * @param uploadPath 要上传到的路径 * @return * @throws IOException */ public static String upload(MultipartFile file, String uploadPath) throws IOException {String finalFileName = ""; if (file.getSize() > 0) { String originalFilename = file.getOriginalFilename(); //获取源文件的后缀名 String extName = originalFilename.substring(originalFilename.lastIndexOf(".")); //获取年月 SimpleDateFormat sdfYyyyMMdd = new SimpleDateFormat("yyyy-MM"); finalFileName = sdfYyyyMMdd.format(new Date()) + "/"; //获取日 SimpleDateFormat sdfdd = new SimpleDateFormat("dd"); finalFileName += sdfdd.format(new Date()) + "/"; //获取时分秒 SimpleDateFormat sdfHHmmss = new SimpleDateFormat("HHmmss"); finalFileName += sdfHHmmss.format(new Date()); //生成4位随机数字 Integer rndNum = new Random().nextInt(1000)+9000; //拼接随机数字和后缀名 finalFileName += rndNum + extName; //目标文件 File f1 = new File(uploadPath+finalFileName); if (!f1.exists()) { f1.mkdirs(); } //开始上传 file.transferTo(f1); } return finalFileName; }}

博主寄语
至此,系统到此完美结束,该案例通俗易懂,详细一步步带入,通过本案例,可提高你的学习能力以及训练自己的逻辑思维能力,认真学习的你很耀眼,相信你的技术一定会有一个质的飞跃,加油,努力练习,祝你成为你想要成为的人!
若在本项目中遇到技术难题,可在下方评论区留言或私信我,授人以鱼不如授人以渔
如果你觉得博主写的不错的话,不妨给个一键三连,点击下方小拳头即可一键三连。
【前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~】前后端分离|前后端分离 -- 深入浅出 Spring Boot + Vue + ElementUI 实现相册管理系统【文件上传 分页 】 文件上传也不过如此~
文章图片

    推荐阅读