<导航

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

 

posted @ 2019-11-10 20:34  字节悦动  阅读(8388)  评论(0编辑  收藏  举报