前后端分离|前后端分离 -- 深入浅出 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 + MyBatis + Maven
前端:Vue + ElementUI
工具:前端使用WebStorm,后端使用IDEA
放松一下~
文章图片
适度适度~
文章图片
挺解乏的哦~
言归正传~
项目风格 请求方式统一为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
项目结构 前端结构
文章图片
后端结构
文章图片
项目难点 前端部分难点:
上传文件采用elementui控件的el-upload,要求不可自动上传,所以设置自动上传为false 其中,要先保存数据到数据库在进行保存图片路径存入数据库,通过存入的数据id去修改当前的数据
显示图片时采用了provide / inject组合控制的显示 因为上传成功后需要再次刷新,如果不刷新,图片不出来,那就要重新刷新页面,但刷新页面对用户来说极不友好,而且时间慢,效率低,所以采用该显示方式,完美解决了二次加载的问题
介绍provide / inject组合控制的显示到底怎么用 首先在app.vue中加入如下代码
app.vue
@import '//at.alicdn.com/t/font_2048717_67mh6lqgbh.css';
在要二次加载的vue文件中加入provide
文章图片
执行完上传图片代码后,进行二次加载
文章图片
完美解决二次加载
核心源码 前端源码 PictureList.vue
搜索 新增
修改
删除
选取文件
只能上传png/jpg/gif/bmp文件,且不超过5M
确定
取消 .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实现员工管理系统 Vue如此简单~
- vue|一分钟教你快速 搭建Vue脚手架(Vue-Cli)项目并整合ElementUI
- 前端|Vue 学习笔记(一)
- 前端|一个简单炫酷的前端小项目(html+css+js)----3D图片演示
- Vue中使用watch同时监听多个值的实现方法
- java人生|新来的23岁Java开发上来秀了波操作,把我们吓到了
- 读读源码|【源码】HashMap源码学习笔记
- 分布式|常用唯一ID生成方案分析(从单机到分布式)
- 日常配置|基于虚拟机下的win7系统安装简记