目录
1、SpringBoot实现文件上传,查询、删除、批量删除和更新
2、header头像信息更新:子组件Person-》父Manage=》 子组件Header
一、上传文件
1、SpringBoot实现文件上传,查询、删除、批量删除和更新
package com.example.demo.controller;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.demo.common.Result;
import com.example.demo.entity.Files;
import com.example.demo.entity.User;
import com.example.demo.mapper.FileMapper;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.net.URLEncoder;
import java.util.List;
@RestController
@RequestMapping("/file")
public class FileController {
@Value("${files.upload.path}")
private String fileUploadPath;
@Resource
private FileMapper fileMapper;
/**
* 文件上传
*
* @param file
* @return
* @throws IOException
*/
@PostMapping("/upload")
public String upload(@RequestParam MultipartFile file) throws IOException {
String originalFileName = file.getOriginalFilename();
String type = FileUtil.extName(originalFileName);
long size = file.getSize();
//存储磁盘
File uploadParentFile = new File(fileUploadPath);
if (!uploadParentFile.exists()) {
uploadParentFile.mkdir();
}
String uuid = IdUtil.fastSimpleUUID();
String fileUuid = uuid + StrUtil.DOT + type;
File uploadFile = new File(fileUploadPath + fileUuid);
//当文件存在的时候获取文件的md5
String url;
String md5;
file.transferTo(uploadFile);
md5 = SecureUtil.md5(uploadFile);
//获取文件的md5,避免相同文件重复上传
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("md5", md5);
//从数据库查询,避免相同文件记录
List<Files> filesList = fileMapper.selectList(queryWrapper);
Files dbFiles = filesList.size() == 0 ? null : filesList.get(0);
if (dbFiles != null) {
url = dbFiles.getUrl();
//由于文件已存在,删除刚才上传重复的文件
uploadFile.delete();
} else {
//文件不存在重复文件,不删除刚才上传文件
url = "http://localhost:9090/file/" + fileUuid;
}
//存储数据库
Files saveFile = new Files();
saveFile.setName(originalFileName);
saveFile.setType(type);
saveFile.setSize(size / 1024);
saveFile.setUrl(url);
saveFile.setMd5(md5);
fileMapper.insert(saveFile);
return url;
}
/**
* 文件下载接口
*
* @param fileUuid
* @param response
* @throws IOException
*/
@GetMapping("/fileUuid")
public void download(@PathVariable String fileUuid, HttpServletResponse response) throws IOException {
File uploadFile = new File(fileUploadPath + fileUuid);
ServletOutputStream os = response.getOutputStream();
response.addHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileUuid, "UTF-8"));
response.setContentType("application/octet-Stream");
os.write(FileUtil.readBytes(uploadFile));
os.flush();
os.close();
}
/**
* 分页查询
*
* @param pageNum
* @param pageSize
* @param name
* @return
*/
@GetMapping("/page")
public Result findPage(@RequestParam Integer pageNum, @RequestParam Integer pageSize,
@RequestParam String name) {
IPage<Files> page = new Page<>(pageNum, pageSize);
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("is_delete", false);
if (!"".equals(name)) {
queryWrapper.like("name", name);
}
queryWrapper.orderByDesc("id");
return Result.success(fileMapper.selectPage(page, queryWrapper));
}
/**
* 文件删除
*
* @param id
* @return
*/
@DeleteMapping("/{id}")
public Result delete(@PathVariable Integer id) {
Files files = fileMapper.selectById(id);
files.setIsDelete(true);
return Result.success(fileMapper.updateById(files));
}
/**
* 文件批量删除
*
* @param ids
* @return
*/
@PostMapping("/del/batch")
public Result deleteBatch(@RequestBody List<Integer> ids) {
QueryWrapper<Files> queryWrapper = new QueryWrapper<>();
queryWrapper.in("id", ids);
List<Files> lf = fileMapper.selectList(queryWrapper);
for (Files file : lf) {
file.setIsDelete(true);
fileMapper.updateById(file);
}
return Result.success();
}
/**
* 文件更新
*
* @param files
* @return
*/
@PostMapping("/update")
public Result update(@RequestBody Files files) {
return Result.success(fileMapper.updateById(files));
}
}
public interface FileMapper extends BaseMapper<Files> {
}
2、Vue实现上传、下载、删除、批量删除、更新、查询
File.vue
<template>
<div>
<div style="margin: 10px 0;">
<el-input suffix-icon="el-icon-search" style="width: 200px;" placeholder="请输入名称" class="search" v-model="name" clearable></el-input>
<el-button class="ml-5" type="primary" @click="load">查询</el-button>
<el-button class="ml-5" type="warning" @click="reset">重置</el-button>
</div>
<div style="margin: 10px 0">
<el-upload action="http://localhost:9090/file/upload" :show-file-list="false" :on-success="handleFileUploadSuccess" style="display: inline-block;">
<el-button type="primary" class="ml-5" >上传文件<i class="el-icon-top"></i></el-button>
</el-upload>
<el-popconfirm
class="ml-5"
confirm-button-text='确认'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm ="delBatch" >
<el-button type="danger" slot="reference">批量删除<i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</div>
<el-table :data="tableData" border stripe :header-cell-class-name="headerBg" @selection-change="handleSelectionChange">
>
<el-table-column type="selection" width="55"> </el-table-column>
<el-table-column prop="id" label="ID" >
</el-table-column>
<el-table-column prop="name" label="文件名称">
</el-table-column>
<el-table-column prop="type" label="文件类型" >
</el-table-column>
<el-table-column prop="size" label="文件大小">
</el-table-column>
<el-table-column label="下载">
<template slot-scope="scope">
<el-button type="primary" @click="download(scope.row.url)"></el-button>
</template>
</el-table-column>
<el-table-column prop="enable" label="启用">
<template slot-scope="scope">
<el-switch v-model="scope.row.enable" active-color="#13ce66" inactive-color="#ccc" @change="changeEnable(scope.row)"></el-switch>
</template>
</el-table-column>
<el-table-column label="操作" width="200px" align="center">
<template slot-scope="scope">
<el-popconfirm
class="ml-5"
confirm-button-text='确认'
cancel-button-text='我再想想'
icon="el-icon-info"
icon-color="red"
title="您确定删除吗?"
@confirm ="del(scope.row.id)" >
<el-button type="danger" slot="reference">删除<i class="el-icon-remove-outline"></i></el-button>
</el-popconfirm>
</template>
</el-table-column>
</el-table>
<div style="padding: 10px 0;">
<el-pagination
@size-change="handleSizeChange"
@current-change="handleCurrentChange"
:current-page="pageNum"
:page-sizes="[2, 5, 10, 20]"
:page-size="pageSize"
layout="total, sizes, prev, pager, next, jumper"
:total="total">
</el-pagination>
</div>
</div>
</template>
<script>
export default {
name: 'File',
data(){
return{
tableData:[],
name:'',
multipleSelection:[],
pageNum: 1,
pageSize: 10,
total: 0
}
},
created(){
this.load();
},
methods: {
handleSizeChange(pageSize) {
console.log(pageSize);
this.pageSize = pageSize;
this.load();
},
handleCurrentChange(pageNum) {
console.log(pageNum);
this.pageNum = pageNum;
this.load();
},
load() {
this.request.get("/file/page", {
params: {
pageNum: this.pageNum,
pageSize: this.pageSize,
name: this.name
}
}).then(res => {
console.log(res);
this.tableData = res.data.records;
this.total = res.data.total;
})
},
reset() {
this.name = '',
this.load();
},
del(id) {
this.request.delete("/file/" + id).then(res => {
if (res.code === '200') {
this.$message.success("删除成功");
this.load();
}
else {
this.$message.error("删除失败");
}
});
},
handleSelectionChange(val) {
console.log(val);
this.multipleSelection = val;
},
delBatch() {
let ids = this.multipleSelection.map(v => v.id); //[1,2,3]
this.request.post("/file/del/batch", ids).then(res => {
if (res.code === '200') {
this.$message.success("删除成功");
this.load();
}
else {
this.$message.error("删除失败");
}
});
},
handleFileUploadSuccess(res){
this.load()
},
download(url){
window.open(url)
},
changeEnable(row){
this.request.post("/file/update", row).then(res => {
if (res.code === '200') {
this.$message.success("操作成功");
}
});
}
}
}
</script>
<style scoped>
</style>
二、头像更新
1、Person.vue
<template>
<el-card style="width: 500px">
<el-upload class="avatar-uploader" action="http://localhost:9090/file/upload" :show-file-list="false"
:on-success="handleAvatarSuccess">
<img v-if="form.avatarUrl" :src="avatarUrl" class="avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"></i>
</el-upload>
<el-form label-width="80px" size="small">
<el-form-item label="用户名">
<el-input v-model="form.username" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="昵称">
<el-input v-model="form.nickname" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="邮箱">
<el-input v-model="form.email" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="电话">
<el-input v-model="form.phone" autocomplete="off"></el-input>
</el-form-item>
<el-form-item label="地址">
<el-input v-model="form.address" autocomplete="off"></el-input>
</el-form-item>
<el-form-item>
<el-button type="primary" @click="save">确 定</el-button>
</el-form-item>
</el-form>
</el-card>
</template>
<script>
export default {
name: "Person",
data() {
return {
form: {},
user: localStorage.getItem("user") ? JSON.parse(localStorage.getItem("user")) : {}
}
},
created() {
this.getUser().then(res => {
this.form = res
})
},
methods: {
async getUser() {
return (await this.request.get("/user/username/" + this.user.username)).data
},
save() {
this.request.post("/user", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功");
//更新浏览器存储的用户信息
this.getUser().then(res => {
res.token = JSON.parse(localStorage.getItem("user")).token
localStorage.setItem("user", JSON.stringify(user))
})
} else {
this.$message.error("保存失败");
}
});
},
handleAvatarSuccess(res) {
this.form.avatarUrl = res
}
}
}
</script>
<style scoped>
.avatar-uploader {
text-align: center;
padding-bottom: 5px;
}
.avatar-uploader .el-upload {
border: 1px dashed #d9d9d9;
border-radius: 6px;
cursor: pointer;
position: relative;
overflow: hidden;
}
.avatar-uploader .el-upload:hover {
border-color: #409EFF;
}
.avatar-uploader-icon {
font-size: 28px;
color: #8c939d;
width: 138px;
height: 138px;
line-height: 138px;
text-align: center;
}
.avatar {
width: 138px;
height: 138px;
display: block;
}
</style>
2、header头像信息更新:子组件Person-》父Manage=》 子组件Header
1)Person.vue: //触发父级更新User的事件refreshUser
save() {
this.request.post("/user", this.form).then(res => {
if (res.code === '200') {
this.$message.success("保存成功");
// //更新浏览器存储的用户信息
// this.getUser().then(res => {
// res.token = JSON.parse(localStorage.getItem("user")).token
// localStorage.setItem("user", JSON.stringify(user))
// })
//触发父级更新User方法
this.emit("refreshUser")
} else {
this.$message.error("保存失败");
}
});
},
2)Manage.vue:定义refreshUser事件的方法
<el-main>
<!-- 当前页面的子路由在当前位置显示 -->
<router-view @refreshUser="getUser"/>
</el-main>
getUser(){
let username = JSON.parse(localStorage.getItem("user"))?JSON.parse(localStorage.getItem("user")).username:""
this.request.get("/user/username/" + username).then(res=>{
//重新赋值
this.user = res.data
})
},
created(){
//从后台取最新数据
this.getUser
},
data() {
return {
collapseBtnClass: 'el-icon-s-fold',
isCollapse: false,
sideWidth: 200,
logoTextShow: true,
user: {}
};
},