springboot 上传下载、导入导出
一、上传下载功能样例
application.yml配置文件上传大小限制
#上传文件设置 springboot上传文件默认支持的大小为 1mb spring: servlet: multipart: #单个数据的大小 max-file-size: 20MB #总数据的大小 max-request-size: 100MB
上传下载功能代码
package com.example.code.bot_monomer.controller.common; /** * @author: shf * description: 文件的上传下载 * date: 2019/11/9 21:04 */ import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.URLEncoder; import java.util.List; import java.util.Objects; import java.util.UUID; import java.util.stream.Collectors; import java.util.stream.Stream; @RestController @RequestMapping("/fileUpOrDown") public class UploadController { /** * 上传单个文件 */ @PostMapping("/uploadSingle") public String uploadSingleFile(@RequestParam("fileUpName") MultipartFile file) {//HttpServletRequest request /** * 这里提到两种接收参数的方式:需要注意一点区别 下面的上传多个文件也是同理 * 直接用 @RequestParam("fileUpName") MultipartFile file * 接收文件参数 如果前端没有选择文件 请求后台报错,Current request is not a multipart request * 前端显示的是500错误 * 替换为 HttpServletRequest request * MultipartFile file = ((MultipartHttpServletRequest)request).getFile("fileUpName"); 获取文件参数 * 如果没有选择文件 后台报错 cannot be cast to org.springframework.web.multipart.MultipartHttpServletRequest * 不过方便在该行代码做异常处理等返回设置对应的code msg等统一形式。 */ //MultipartFile file = ((MultipartHttpServletRequest)request).getFile("fileUpName"); if (file.isEmpty()) { return "上传文件不能为空"; } //获取文件名,带后缀 String fileName = file.getOriginalFilename(); /*如果限制文件上传类型例如:该接口限制只能上传图片,则增加图片格式校验*/ List<String> imageType = Stream.of("jpg","jpeg", "png", "bmp", "gif").collect(Collectors.toList()); // 获取文件的后缀格式 String fileSuffix = fileName.substring(fileName.lastIndexOf(".") + 1).toLowerCase(); if (!imageType.contains(fileSuffix)) return "非法文件"; //加个UUID拼接,尽量避免文件名称重复 String path = "E:" + File.separator + "ces" + File.separator + UUID.randomUUID().toString().replace("-","") + "_" + fileName; File dest = new File(path); //判断文件是否已经存在,如果可以直接覆盖则忽略 或 再重新生成该文件的时间戳文件直到不重复 if (dest.exists()) return "上传的文件名已存在"; //判断文件父目录是否存在 if (!dest.getParentFile().exists()) dest.getParentFile().mkdir(); //保存文件 try { file.transferTo(dest); } catch (IOException e) { e.printStackTrace(); return "上传文件异常"; } return "Success"; } /** * 上传多个文件 */ @PostMapping("/uploadMore") public String uploadMoreFile(@RequestParam("fileNames") List<MultipartFile> files) {//HttpServletRequest request //List<MultipartFile> files = ((MultipartHttpServletRequest)request).getFiles("fileName"); if (Objects.isNull(files) || files.size() < 1) return "文件不能为空"; for (MultipartFile file : files) { String fileName = file.getOriginalFilename(); //加个UUID拼接,尽量避免文件名称重复 String path = "E:" + File.separator + "ces" + File.separator + UUID.randomUUID().toString().replace("-","") + "_" + fileName; File dest = new File(path); //判断文件是否已经存在,如果可以直接覆盖则忽略 或 再重新生成该文件的时间戳文件直到不重复 //if (dest.exists()) return "上传的文件名已存在"; //判断文件父目录是否存在 if (!dest.getParentFile().exists()) dest.getParentFile().mkdir(); //保存文件 try { file.transferTo(dest); } catch (IOException e) { e.printStackTrace(); return "上传文件异常"; } } return "Success"; } /** * 下载文件 */ @RequestMapping("/downLoadFile") public String downLoadFile(HttpServletResponse response, @RequestParam("fileName") String filePathName) { File file = new File(filePathName); if (!file.exists()) return "文件不存在"; try( InputStream inStream = new FileInputStream(filePathName); OutputStream os = response.getOutputStream(); ) { response.reset(); response.setHeader("Content-Disposition", "attachment;fileName=" + URLEncoder.encode(filePathName,"UTF-8")); byte[] buff = new byte[1024]; int len = -1; while ((len = inStream.read(buff)) > 0) { os.write(buff, 0, len); } os.flush(); } catch (Exception e) { e.printStackTrace(); return "下载文件异常"; } return "Success"; } }
二、导入导出Excel
java中比较流行的用poi,但是每次都要写大段工具类来搞定这事儿,此处推荐一个别人造好的轮子【easypoi】。
1、引入依赖
<!--easypoi--> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-base</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-web</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>cn.afterturn</groupId> <artifactId>easypoi-annotation</artifactId> <version>3.0.3</version> </dependency>
2、编写实体类
- 处注意必须要有空构造函数,否则会报错“对象创建错误”
- 关于注解@Excel,其他还有@ExcelCollection,@ExcelEntity ,@ExcelIgnore,@ExcelTarget等,此处我们用不到,可以去官方查看更多
属性 | 类型 | 类型 | 说明 |
---|---|---|---|
name |
String |
null |
列名 |
needMerge |
boolean |
fasle |
纵向合并单元格 |
orderNum |
String |
"0" |
列的排序,支持name_id |
replace |
String[] |
{} |
值得替换 导出是{a_id,b_id} 导入反过来 |
savePath |
String |
"upload" |
导入文件保存路径 |
type |
int |
1 |
导出类型 1 是文本 2 是图片,3 是函数,10 是数字 默认是文本 |
width |
double |
10 |
列宽 |
height |
double |
10 |
列高,后期打算统一使用@ExcelTarget的height,这个会被废弃,注意 |
isStatistics |
boolean |
fasle |
自动统计数据,在追加一行统计,把所有数据都和输出这个处理会吞没异常,请注意这一点 |
isHyperlink |
boolean |
false |
超链接,如果是需要实现接口返回对象 |
isImportField |
boolean |
true |
校验字段,看看这个字段是不是导入的Excel中有,如果没有说明是错误的Excel,读取失败,支持name_id |
exportFormat |
String |
"" |
导出的时间格式,以这个是否为空来判断是否需要格式化日期 |
importFormat |
String |
"" |
导入的时间格式,以这个是否为空来判断是否需要格式化日期 |
format |
String |
"" |
时间格式,相当于同时设置了exportFormat 和 importFormat |
databaseFormat |
String |
"yyyyMMddHHmmss" |
导出时间设置,如果字段是Date类型则不需要设置 数据库如果是string 类型,这个需要设置这个数据库格式,用以转换时间格式输出 |
numFormat |
String |
"" |
数字格式化,参数是Pattern,使用的对象是DecimalFormat |
imageType |
int |
1 |
导出类型 1 从file读取 2 是从数据库中读取 默认是文件 同样导入也是一样的 |
suffix |
String |
"" |
文字后缀,如% 90 变成90% |
isWrap |
boolean |
true |
是否换行 即支持\n |
mergeRely |
int[] |
{} |
合并单元格依赖关系,比如第二列合并是基于第一列 则{1}就可以了 |
mergeVertical |
boolean |
fasle |
纵向合并内容相同的单元格 |
UserEntity
package com.example.code.bot_monomer.entity; import cn.afterturn.easypoi.excel.annotation.Excel; import com.baomidou.mybatisplus.annotation.TableName; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; import lombok.NoArgsConstructor; import java.io.Serializable; import java.util.Date; /** * @author: shf * description: * date: 2019/11/9 20:08 */ @Data @AllArgsConstructor @NoArgsConstructor @Builder @TableName("user") public class UserEntity implements Serializable { private static final long serialVersionUID = 1L; @Excel(name = "ID", orderNum = "0") private Long id; @Excel(name = "姓名", orderNum = "1") private String userName; @Excel(name = "年龄", orderNum = "2") private Integer age; @Excel(name = "邮箱", orderNum = "3") private String email; @Excel(name = "出生日期", exportFormat = "yyyy-MM-dd",importFormat="yyyy-MM-dd",orderNum = "4") private Date birth; }
ExcelUtil工具类
package com.example.code.bot_monomer.utils; import cn.afterturn.easypoi.excel.ExcelExportUtil; import cn.afterturn.easypoi.excel.ExcelImportUtil; import cn.afterturn.easypoi.excel.entity.ExportParams; import cn.afterturn.easypoi.excel.entity.ImportParams; import cn.afterturn.easypoi.excel.entity.enmus.ExcelType; import org.apache.commons.lang3.StringUtils; import org.apache.poi.ss.usermodel.Workbook; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.File; import java.io.IOException; import java.net.URLEncoder; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; /** * @author: shf * description: * date: 2019/11/10 18:51 */ public class ExcelUtil { public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,String fileName,boolean isCreateHeader, HttpServletResponse response){ ExportParams exportParams = new ExportParams(title, sheetName); exportParams.setCreateHeadRows(isCreateHeader); defaultExport(list, pojoClass, fileName, response, exportParams); } public static void exportExcel(List<?> list, String title, String sheetName, Class<?> pojoClass,String fileName, HttpServletResponse response){ defaultExport(list, pojoClass, fileName, response, new ExportParams(title, sheetName)); } public static void exportExcel(List<Map<String, Object>> list, String fileName, HttpServletResponse response){ defaultExport(list, fileName, response); } private static void defaultExport(List<?> list, Class<?> pojoClass, String fileName, HttpServletResponse response, ExportParams exportParams) { Workbook workbook = ExcelExportUtil.exportExcel(exportParams,pojoClass,list); if (workbook != null); downLoadExcel(fileName, response, workbook); } private static void downLoadExcel(String fileName, HttpServletResponse response, Workbook workbook) { try { response.setCharacterEncoding("UTF-8"); response.setHeader("content-Type", "application/vnd.ms-excel"); response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8")); workbook.write(response.getOutputStream()); } catch (IOException e) { //throw new NormalException(e.getMessage()); e.printStackTrace(); } } private static void defaultExport(List<Map<String, Object>> list, String fileName, HttpServletResponse response) { Workbook workbook = ExcelExportUtil.exportExcel(list, ExcelType.HSSF); if (workbook != null); downLoadExcel(fileName, response, workbook); } public static <T> List<T> importExcel(String filePath,Integer titleRows,Integer headerRows, Class<T> pojoClass){ if (StringUtils.isBlank(filePath)){ return null; } ImportParams params = new ImportParams(); params.setTitleRows(titleRows); params.setHeadRows(headerRows); List<T> list = null; try { list = ExcelImportUtil.importExcel(new File(filePath), pojoClass, params); }catch (NoSuchElementException e){ //throw new NormalException("模板不能为空"); e.printStackTrace(); } catch (Exception e) { e.printStackTrace(); //throw new NormalException(e.getMessage()); } return list; } public static <T> List<T> importExcel(MultipartFile file, Integer titleRows, Integer headerRows, Class<T> pojoClass){ if (file == null){ return null; } ImportParams params = new ImportParams(); params.setTitleRows(titleRows); params.setHeadRows(headerRows); List<T> list = null; try { list = ExcelImportUtil.importExcel(file.getInputStream(), pojoClass, params); }catch (NoSuchElementException e){ // throw new NormalException("excel文件不能为空"); e.printStackTrace(); } catch (Exception e) { //throw new NormalException(e.getMessage()); e.printStackTrace(); } return list; } }
测试Controller
package com.example.code.bot_monomer.controller.common; import com.example.code.bot_monomer.entity.UserEntity; import com.example.code.bot_monomer.utils.ExcelUtil; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.util.Date; import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; /** * @author: shf * description: * date: 2019/11/10 18:55 */ @RestController @RequestMapping("/excel") public class ExcelController { /** * Excel导出 */ @RequestMapping("exportExcel") public void exportExcel(HttpServletResponse response) throws IOException { UserEntity user1 = UserEntity.builder().id(1L).userName("张三").age(10).birth(new Date()).build(); UserEntity user2 = UserEntity.builder().id(2L).userName("小李").age(16).birth(new Date()).build(); UserEntity user3 = UserEntity.builder().id(3L).userName("小王").age(14).birth(new Date()).build(); List<UserEntity> userList = Stream.of(user1, user2, user3).collect(Collectors.toList()); //导出操作 ExcelUtil.exportExcel(userList, null, "用户", UserEntity.class, "测试用户导出.xlsx", response); } /** * Excel导入 */ @PostMapping("importExcel") public String importExcel(HttpServletResponse response, @RequestParam("file") MultipartFile file) { //解析excel List<UserEntity> userList = ExcelUtil.importExcel(file, 0, 1, UserEntity.class); //也可以使用String filePath = "xxx.xls";importExcel(String filePath,Integer titleRows,Integer headerRows, Class<T> pojoClass)导入 System.out.println("导入数据一共【" + userList.size() + "】行"); System.out.println("导入的数据:" + userList); //TODO 保存数据库 return "Success"; } }
异常处理:
try { EasyExcelUtil.exportExcel(exporDatatList, null, "用户列表", ActiveFissionUserDto.class, "用户列表.xlsx", response); } catch (Exception e) { log.error(">>>用户导出Excel异常:", e); exportUserExcelError(response); } //-------------------------------------------- private void exportUserExcelError(HttpServletResponse response) throws IOException { response.setHeader("content-type", "text/html;charset=UTF-8"); PrintWriter writer = response.getWriter(); writer.print("导出异常"); writer.flush(); writer.close(); }
参考文章:
https://www.cnblogs.com/shihaiming/p/9415102.html
http://easypoi.mydoc.io/#category_41961