>
>com.qcloud >
>cos_api >
>5.6.89 >
>
需要自己配置的参数
tmpSecretId
tmpSecretKey
COS_REGION
localFilePath:要上传的文件所在磁盘路径
bucketName
exampleobject:上传到腾讯云 哪个文件夹下以及上传文件的名称 如 “/图片/5.jpg”
import com.alibaba.fastjson.JSON;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.region.Region;
import java.io.File;
public class TestCos {
public static void main(String[] args) {
// 1 传入获取到的临时密钥 (tmpSecretId, tmpSecretKey, sessionToken)
String tmpSecretId = "SECRETID";
String tmpSecretKey = "SECRETKEY";
String sessionToken = "TOKEN";
BasicSessionCredentials cred = new BasicSessionCredentials(tmpSecretId, tmpSecretKey, sessionToken);
// 2 设置 bucket 的地域, COS 地域的简称请参阅 https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参阅源码或者常见问题 Java SDK 部分
Region region = new Region("COS_REGION");
ClientConfig clientConfig = new ClientConfig(region);
// 3 生成 cos 客户端
COSClient cosClient = new COSClient(cred, clientConfig);
// 指定要上传的文件
File localFile = new File(localFilePath);
// 指定文件将要存放的存储桶
String bucketName = "examplebucket-1250000000";
// 指定文件上传到 COS 上的路径,即对象键。例如对象键为folder/picture.jpg,则表示将文件 picture.jpg 上传到 folder 路径下
String key = "exampleobject";
PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, key, localFile);
PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
}
spring.servlet.multipart.max-file-size=1024MB
spring.servlet.multipart.max-request-size=1024MB
#不同的服务器,地址不同
tencent.cos.file.region=ap-beijing
tencent.cos.file.secretid=你的id
tencent.cos.file.secretkey=你的key
#bucket可以在控制台创建,也可以使用java代码创建
tencent.cos.file.bucketname=你的bucketName
package com.jq.vod.utils;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
@Component
public class ConstantPropertiesUtil implements InitializingBean {
@Value("${tencent.cos.file.region}") //读取配置文件的值
private String region;
@Value("${tencent.cos.file.secretid}")
private String secretId;
@Value("${tencent.cos.file.secretkey}")
private String secretKey;
@Value("${tencent.cos.file.bucketname}")
private String bucketName;
public static String END_POINT;
public static String ACCESS_KEY_ID;
public static String ACCESS_KEY_SECRET;
public static String BUCKET_NAME;
@Override
public void afterPropertiesSet() throws Exception {
END_POINT=region;
ACCESS_KEY_ID = secretId;
ACCESS_KEY_SECRET = secretKey;
BUCKET_NAME = bucketName;
}
}
package com.jq.vod.controller;
import com.jq.result.Result;
import com.jq.vod.service.FileService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
@Api(tags = "文件上传接口")
@RestController
@RequestMapping("/admin/vod/file")
@CrossOrigin
public class FileUploadController {
@Autowired
private FileService fileService;
@ApiOperation("文件上传")
@PostMapping("upload")
public Result uploadFile(MultipartFile file){
String url=fileService.upload(file);
return Result.ok(url).message("上传文件成功");
}
}
package com.jq.vod.service;
import org.springframework.web.multipart.MultipartFile;
public interface FileService {
//文件上传
String upload(MultipartFile file);
}
package com.jq.vod.service.impl;
import com.jq.vod.service.FileService;
import com.jq.vod.utils.ConstantPropertiesUtil;
import com.qcloud.cos.COSClient;
import com.qcloud.cos.ClientConfig;
import com.qcloud.cos.auth.BasicCOSCredentials;
import com.qcloud.cos.auth.COSCredentials;
import com.qcloud.cos.exception.CosClientException;
import com.qcloud.cos.exception.CosServiceException;
import com.qcloud.cos.http.HttpProtocol;
import com.qcloud.cos.model.ObjectMetadata;
import com.qcloud.cos.model.PutObjectRequest;
import com.qcloud.cos.model.PutObjectResult;
import com.qcloud.cos.model.UploadResult;
import com.qcloud.cos.region.Region;
import com.qcloud.cos.transfer.Upload;
import org.joda.time.DateTime;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.util.UUID;
@Service
public class FileServiceImpl implements FileService {
@Override
public String upload(MultipartFile file) {
// 1 初始化用户身份信息(secretId, secretKey)。
// SECRETID和SECRETKEY请登录访问管理控制台 https://console.cloud.tencent.com/cam/capi 进行查看和管理
String secretId = ConstantPropertiesUtil.ACCESS_KEY_ID;
String secretKey = ConstantPropertiesUtil.ACCESS_KEY_SECRET;
COSCredentials cred = new BasicCOSCredentials(secretId, secretKey);
// 2 设置 bucket 的地域, COS 地域的简称请参照 https://cloud.tencent.com/document/product/436/6224
// clientConfig 中包含了设置 region, https(默认 http), 超时, 代理等 set 方法, 使用可参见源码或者常见问题 Java SDK 部分。
Region region = new Region(ConstantPropertiesUtil.END_POINT);
ClientConfig clientConfig = new ClientConfig(region);
// 这里建议设置使用 https 协议
// 从 5.6.54 版本开始,默认使用了 https
clientConfig.setHttpProtocol(HttpProtocol.https);
// 3 生成 cos 客户端。
COSClient cosClient = new COSClient(cred, clientConfig);
// 存储桶的命名格式为 BucketName-APPID,此处填写的存储桶名称必须为此格式
String bucketName = ConstantPropertiesUtil.BUCKET_NAME;
// 对象键(Key)是对象在存储桶中的唯一标识。
//在文件名称的前面,添加uuid值保证,上传的文件名称不一样
String key = UUID.randomUUID().toString().replaceAll("-","")
+file.getOriginalFilename();
//对上传文件分组,根据当前日期
String dateTime = new DateTime().toString("yyyy/MM/dd");
key=dateTime+"/"+key;
try {
//获取上传文件的输入流
InputStream inputStream = file.getInputStream();
ObjectMetadata objectMetadata = new ObjectMetadata();
PutObjectRequest putObjectRequest = new PutObjectRequest(
bucketName,
key,
inputStream,
objectMetadata);
// 高级接口会返回一个异步结果Upload
PutObjectResult putObjectResult = cosClient.putObject(putObjectRequest);
//返回上传文件路径
//https://ggkt-1313198864.cos.ap-beijing.myqcloud.com/image/ggkt/HELP.md
String url="https://"+bucketName+"."+"cos"+"."+ConstantPropertiesUtil.END_POINT+".myqcloud.com"+"/image/ggkt/"+key;
return url;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
}
<!-- 讲师头像 -->
<el-form-item label="讲师头像">
<el-upload
:show-file-list="false"
:on-success="handleAvatarSuccess"
:before-upload="beforeAvatarUpload"
:on-error="handleAvatarError"
:action="BASE_API+'/admin/vod/file/upload?module=avatar'"
class="avatar-uploader">
<img v-if="teacher.avatar" :src="teacher.avatar">
<i v-else class="el-icon-plus avatar-uploader-icon"/>
</el-upload>
</el-form-item>
// 上传成功回调
handleAvatarSuccess(res, file) {
// console.log(res)
if (res.code==200) {
// console.log(res)
this.teacher.avatar = res.data
// 强制重新渲染
this.$forceUpdate()
} else {
this.$message.error('上传失败 (非0)')
}
},
// 错误处理
handleAvatarError() {
console.log('error')
this.$message.error('上传失败(http失败)')
},
// 上传校验
beforeAvatarUpload(file) {
const isJPG = file.type === 'image/jpeg'
const isLt2M = file.size / 1024 / 1024 < 2
if (!isJPG) {
this.$message.error('上传头像图片只能是 JPG 格式!')
}
if (!isLt2M) {
this.$message.error('上传头像图片大小不能超过 2MB!')
}
return isJPG && isLt2M
}
基于element-ui组件来进行
//课程分类列表
{
path: '/subject',
component: Layout,
redirect: '/subject/list',
name: '课程分类管理',
alwaysShow: true,
meta: { title: '课程分类管理', icon: 'example' },
children: [
{
path: 'list',
name: '课程分类列表',
component: () => import('@/views/vod/subject/list'),
meta: { title: '课程分类列表', icon: 'table' }
}
]
},
<template>
<div class="app-container">
<el-table
:data="list"
style="width: 100%"
row-key="id"
border
lazy
:load="load"
:tree-props="{children: 'children', hasChildren: 'hasChildren'}">
<el-table-column
prop="title"
label="名称"
width="150">
</el-table-column>
<el-table-column
prop="createTime"
label="创建时间">
</el-table-column>
</el-table>
</div>
</template>
<script>
import subjectApi from '@/api/vod/subject'
export default {
data() {
return {
list:[] //数据字典列表数组
}
},
created() {
this.getSubList(0)
},
methods: {
//数据字典列表
getSubList(id) {
subjectApi.getChildList(id)
.then(response => {
this.list = response.data
})
},
load(tree, treeNode, resolve) {
subjectApi.getChildList(tree.id).then(response => {
resolve(response.data)
})
}
}
}
</script>
import request from '@/utils/request'
const api_name = '/admin/vod/subject'
export default {
//课程分类的列表接口
getChildList(id) {
return request({
url: `${api_name}/getChildSubject/${id}`,
method: 'get'
})
}
}
课程分类采用树形展示,使用“树形数据与懒加载”的方式展现数据列表,,页面搜索:树形数据与懒加载
package com.jq.vod.controller;
import com.jq.model.vod.Subject;
import com.jq.result.Result;
import com.jq.vod.service.SubjectService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.util.List;
/**
*
* 课程科目 前端控制器
*
*
* @author CJQ
* @since 2022-08-05
*/
@Api(tags = "课程分类管理接口")
@RestController
@RequestMapping("/admin/vod/subject")
@CrossOrigin
public class SubjectController {
@Autowired
public SubjectService subjectService;
//课程分类列表
//懒加载,每次只查询的事一层数据
@ApiOperation("课程分类列表")
@GetMapping("getChildSubject/{id}")
public Result getChildSubject(@PathVariable Long id){
List<Subject> list= subjectService.selectSubjectList(id);
return Result.ok(list);
}
}
package com.jq.vod.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.jq.model.vod.Subject;
/**
*
* 课程科目 Mapper 接口
*
*
* @author CJQ
* @since 2022-08-05
*/
public interface SubjectMapper extends BaseMapper<Subject> {
}
package com.jq.vod.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jq.model.vod.Subject;
import java.util.List;
/**
*
* 课程科目 服务类
*
*
* @author CJQ
* @since 2022-08-05
*/
public interface SubjectService extends IService<Subject> {
//课程分类列表
//懒加载,每次只查询的事一层数据
List<Subject> selectSubjectList(Long id);
}
package com.jq.vod.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.jq.model.vod.Subject;
import com.jq.vod.mapper.SubjectMapper;
import com.jq.vod.service.SubjectService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
*
* 课程科目 服务实现类
*
*
* @author CJQ
* @since 2022-08-05
*/
@Service
public class SubjectServiceImpl extends ServiceImpl<SubjectMapper, Subject> implements SubjectService {
//课程分类列表
//懒加载,每次只查询的事一层数据
@Override
public List<Subject> selectSubjectList(Long id) {
//SELECT * FROM SUBJECT WHERE parent_id=0
QueryWrapper<Subject>wrapper =new QueryWrapper<>();
wrapper.eq("parent_id",id);
List<Subject> subjectList = baseMapper.selectList(wrapper);
//subjectList遍历,得到每个subject对象,判断是否有下一层数据,有hasChildren =true
for (Subject subject:subjectList) {
//获取subject的id值
Long subjectId = subject.getId();
//查询
boolean isChild=this.isChilden(subjectId);
//封装到对象中
subject.setHasChildren(isChild);
}
return subjectList;
}
//判断是否有下一层的数据
private boolean isChilden(Long subjectId){
QueryWrapper<Subject> wrapper=new QueryWrapper<>();
wrapper.eq("parent_id",subjectId);
Integer count = baseMapper.selectCount(wrapper);
return count>0;
}
}
导出是从前端页面查询的数据,导出到Excel中
list.vue添加导出按钮组件
<div class="el-toolbar">
<div class="el-toolbar-body" style="justify-content: flex-start;">
<el-button type="text" @click="exportData"><i class="fa fa-plus"/> 导出</el-button>
</div>
</div>
添加方法
exportData() {
window.open("http://localhost:8301/admin/vod/subject/exportData")
},
@Data
public class SubjectEeVo {
@ExcelProperty(value = "id" ,index = 0)
private Long id;
@ExcelProperty(value = "课程分类名称" ,index = 1)
private String title;
@ExcelProperty(value = "上级id" ,index = 2)
private Long parentId;
@ExcelProperty(value = "排序" ,index = 3)
private Integer sort;
}
/**
* 课程分类导出
* @param response
*/
@ApiOperation("课程分类导出")
@GetMapping("exportData")
public void exportData(HttpServletResponse response){
subjectService.exportData(response);
}
package com.jq.vod.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jq.model.vod.Subject;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
*
* 课程科目 服务类
*
*
* @author CJQ
* @since 2022-08-05
*/
public interface SubjectService extends IService<Subject> {
//课程分类列表
//懒加载,每次只查询的事一层数据
List<Subject> selectSubjectList(Long id);
//课程分类导出
void exportData(HttpServletResponse response);
}
/**
* 课程分类导出
* @param response
*/
@Override
public void exportData(HttpServletResponse response) {
try {
// 设置下载信息
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 这里URLEncoder.encode可以防止中文乱码 当然和easyexcel没有关系
String fileName = URLEncoder.encode("课程分类", "UTF-8");
response.setHeader("Content-disposition", "attachment;filename="+ fileName + ".xlsx");
//查询课程分类所有数据
List<Subject> subjectList = baseMapper.selectList(null);
//List --->List
List<SubjectEeVo> subjectEeVoList=new ArrayList<>();
for (Subject subject:subjectList) {
SubjectEeVo subjectEeVo =new SubjectEeVo();
// subjectEeVo.setId(subject.getId());
// subjectEeVo.setParentId(subject.getParentId());
BeanUtils.copyProperties(subject,subjectEeVo);
subjectEeVoList.add(subjectEeVo);
}
//EasyExcel写操作
EasyExcel.write(response.getOutputStream(), SubjectEeVo.class)
.sheet("课程分类")
.doWrite(subjectEeVoList);
}catch (Exception e){
throw new GgktException(20001,"导出失败");
}
}
前端上传Excel表格,将数据导入到数据库中
导入按钮组件
<el-button type="text" @click="importData"><i class="fa fa-plus"/> 导入</el-button>
对应方法
importData() {
this.dialogImportVisible = true
},
onUploadSuccess(response, file) {
this.$message.info('上传成功')
this.dialogImportVisible = false
this.getSubList(0)
},
导入文件,弹窗组件
<el-dialog title="导入" :visible.sync="dialogImportVisible" width="480px">
<el-form label-position="right" label-width="170px">
<el-form-item label="文件">
<el-upload
:multiple="false"
:on-success="onUploadSuccess"
:action="'http://localhost:8333/admin/vod/subject/importData'"
class="upload-demo">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传xls文件,且不超过500kb</div>
</el-upload>
</el-form-item>
</el-form>
<div slot="footer" class="dialog-footer">
<el-button @click="dialogImportVisible = false">取消</el-button>
</div>
</el-dialog>
对用属性
data() {
return {
dialogImportVisible: false,
list:[] //数据字典列表数组
}
},
/**
* 课程分类导入
* @param file
*/
@ApiOperation("课程分类导入")
@PostMapping("importData")
public Result importData(MultipartFile file){
subjectService.importData(file);
return Result.ok(null);
}
package com.jq.vod.service;
import com.baomidou.mybatisplus.extension.service.IService;
import com.jq.model.vod.Subject;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
/**
*
* 课程科目 服务类
*
*
* @author CJQ
* @since 2022-08-05
*/
public interface SubjectService extends IService<Subject> {
//课程分类列表
//懒加载,每次只查询的事一层数据
List<Subject> selectSubjectList(Long id);
//课程分类导出
void exportData(HttpServletResponse response);
//课程分类导入
void importData(MultipartFile file);
}
package com.jq.vod.listener;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import com.jq.model.vod.Subject;
import com.jq.vo.vod.SubjectEeVo;
import com.jq.vod.mapper.SubjectMapper;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
@Component
public class SubjectListener extends AnalysisEventListener<SubjectEeVo> {
@Autowired
private SubjectMapper subjectMapper;
/**
* 一行一行的读取Excel的内容,把每行的内容封装到user对象
* 从Excel第二行开始读取
* @param subjectEeVo
* @param analysisContext
*/
@Override
public void invoke(SubjectEeVo subjectEeVo, AnalysisContext analysisContext) {
Subject subject=new Subject();
//SubjectEeVo-->Subject
BeanUtils.copyProperties(subjectEeVo,subject);
//将数据添加到数据库
subjectMapper.insert(subject);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
/**
* 课程分类导入
* @param file
*/
@Override
public void importData(MultipartFile file) {
try {
EasyExcel.read(file.getInputStream(),SubjectEeVo.class,subjectListener)
.sheet().doRead();
} catch (IOException e) {
throw new GgktException(20001,"导入失败");
}
}
EasyExcel是阿里巴巴开源的一个excel处理框架,以使用简单、节省内存著称。
EasyExcel能大大减少占用内存的主要原因是在解析Excel时没有将文件数据一次性全部加载到内存中,而是从磁盘上一行行读取数据,逐个解析。
<dependencies>
<dependency>
<groupId>com.alibabagroupId>
<artifactId>easyexcelartifactId>
<version>2.1.1version>
dependency>
dependencies>
设置表头和添加的数据字段
package com.jq.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class User {
@ExcelProperty(value = "用户编号")
private int id;
@ExcelProperty(value = "用户名称")
private String name;
}
创建方法循环设置要添加到Excel的数据
package com.jq.excel;
import com.alibaba.excel.EasyExcel;
import java.util.ArrayList;
import java.util.List;
public class TestWrite {
public static void main(String[] args) {
//设置文件名称和路径
String fileName="F:\\JavaCode\\agwtest.xlsx";
//调用方法
EasyExcel.write(fileName,User.class)
.sheet("写操作")
.doWrite(data());
}
//循环设置要添加的数据,最终封装到list集合中
private static List<User> data() {
List<User> list = new ArrayList<User>();
for (int i = 0; i < 10; i++) {
User data = new User();
data.setId(i);
data.setName("lucy"+i);
list.add(data);
}
return list;
}
}
package com.jq.excel;
import com.alibaba.excel.annotation.ExcelProperty;
import lombok.Data;
@Data
public class User {
@ExcelProperty(value = "用户编号",index = 0)
private int id;
@ExcelProperty(value = "用户名称",index = 1)
private String name;
}
创建监听器,一行一行的读取
package com.jq.excel;
import com.alibaba.excel.context.AnalysisContext;
import com.alibaba.excel.event.AnalysisEventListener;
import java.util.Map;
public class ExcelListener extends AnalysisEventListener<User> {
/**
* 一行一行的读取Excel的内容,把每行的内容封装到user对象
* 从Excel第二行开始读取
* @param user
* @param analysisContext
*/
@Override
public void invoke(User user, AnalysisContext analysisContext) {
System.out.println(user);
}
/**
* 读取表头内容
* @param headMap
* @param context
*/
@Override
public void invokeHeadMap(Map<Integer, String> headMap, AnalysisContext context) {
System.out.println("表头"+headMap);
}
@Override
public void doAfterAllAnalysed(AnalysisContext analysisContext) {
}
}
package com.jq.excel;
import com.alibaba.excel.EasyExcel;
public class TestRead {
public static void main(String[] args) {
//设置文件名称和路径
String fileName="F:\\JavaCode\\agwtest.xlsx";
//调用方法
EasyExcel.read(fileName,User.class,new ExcelListener()).sheet().doRead();
}
}