上文,我们完成了简单的导入导出,但是是单体环境的读和写。实际成产环境一般都在web环境中,那我们这篇就结合SpringMVC实现文件上传和下载。请在保证熟悉SpringMVC相关知识后食用。
3、文件上传和下载
基于SpringMVC的文件上传和下载
0. 导入依赖
<!-- EasyExcel -->
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>2.0.5</version>
</dependency>
<!-- lombok -->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.10</version>
<scope>provided</scope>
</dependency>
<!-- junit -->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-nop</artifactId>
<version>1.7.2</version>
</dependency>
<!-- SpringMVC(Spring) -->
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-webmvc</artifactId>
<version>5.0.5.RELEASE</version>
</dependency>
<!-- Servlet -->
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>
<version>4.0.1</version>
<scope>provided</scope>
</dependency>
<!-- 文件上传 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
3.1 文件上传
编写excel中每一行对应的实体类
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* 学生姓名
*/
private String name;
/**
* 学生性别
*/
private String gender;
/**
* 学生出生日期
*/
private Date birthday;
/**
* id
*/
private String id;
}
编写回调监听器StudentReadListener
@Component
@Scope("prototype") // 作者要求每次读取都要使用新的Listener
public class StudentReadListener extends AnalysisEventListener<Student> {
@Autowired
private StudentService studentService;
private final int BATCH_SAVE_NUM = 5;
ArrayList<Student> students = new ArrayList<>();
private int count = 0;
// 每读一样,会调用该invoke方法一次
@Override
public void invoke(Student data, AnalysisContext context) {
students.add(data);
if (++count % BATCH_SAVE_NUM == 0) {
studentService.save(students);
students.clear();
}
}
// 全部读完之后,会调用该方法
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
// TODO......
}
}
业务代码接口StudentService和实现类StudentServiceImpl
public interface StudentService {
void save(ArrayList<Student> students);
}
@Service
public class StudentServiceImpl implements StudentService {
@Override
public void save(ArrayList<Student> students) {
System.out.println("students in service = " + students);
}
}
Spring配置文件
<!-- 组件扫描-->
<context:component-scan base-package="net.sunxiaowei"/>
SpringMVC配置文件
<!-- 组件扫描-->
<context:component-scan base-package="net.sunxiaowei.demo"/>
<!-- MVC文件上传多部件解析器 -->
<bean class="org.springframework.web.multipart.commons.CommonsMultipartResolver"
id="multipartResolver"/>
编码读取上传的Excel文件
@Controller
public class WebUploadAndDownload {
/**
* 文件上传
* 1. 编写excel中每一行对应的实体类
* 2. 由于默认异步读取excel,所以需要逐行读取的回调监听器
* 3. 开始读取Excel
*/
@PostMapping("upload")
@ResponseBody
public String upload(MultipartFile file) throws IOException {
ExcelReaderBuilder workBook = EasyExcel.read(file.getInputStream(), Student.class, studentReadListener);
workBook.sheet().doRead();
return "success";
}
3.2 文件下载
编写实体类并创建对象以便写入表格
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
/**
* id
*/
@ExcelIgnore
private String id;
/**
* 学生姓名
*/
//@ExcelProperty({"学员信息表", "学生姓名"})
@ExcelProperty("学生姓名")
private String name;
/**
* 学生性别
*/
//@ExcelProperty({"学员信息表", "学生性别"})
@ExcelProperty("学生性别")
private String gender;
/**
* 学生出生日期
*/
//@ExcelProperty({"学员信息表", "学生出生日期"})
@ExcelProperty("学生出生日期")
private Date birthday;
}
// 循环生成10个学生对象
private static List<Student> initData() {
ArrayList<Student> students = new ArrayList<>();
for (int i = 0; i < 10; i++) {
Student data = new Student();
data.setName("模拟学号0" + i);
data.setBirthday(new Date());
data.setGender("男");
students.add(data);
}
return students;
}
编码将数据写入到响应体实现下载
public class WebUploadAndDownload {
/**
* 文件下载
* 1. 编写实体类并创建对象以便写入表格
* 2. 设置响应参数:文件的ContentType和文件名,同时设置编码避免乱码
* 3. 直接写,内部会调用finish方法自动关闭OutputStream
*/
@GetMapping("download")
public void download(HttpServletResponse response) throws IOException {
response.setContentType("application/vnd.ms-excel");
response.setCharacterEncoding("utf-8");
// 防止中文乱码
String fileName = URLEncoder.encode("测试", "UTF-8");
response.setHeader("Content-Disposition", "attachment; filename*=UTF-8''" + fileName + ".xlsx");
ExcelWriterBuilder workBook = EasyExcel.write(response.getOutputStream(), Student.class);
ExcelWriterSheetBuilder sheet = workBook.sheet("模板");
sheet.doWrite(initData());
}
}
4、自定义单元格样式
EasyExcel支持调整行高、列宽、背景色、字体大小等内容,但是控制方式与使用原生POI无异,比较繁琐,不建议使用。
但是可以使用模板填充的方式,向预设样式的表格中直接写入数据,写入数据的时候会保持原有样式。
本文资料下载地址阿里云盘:EasyExcel资料下载
B站讲解视频:EasyExcel讲解视频
GitHub地址 官方文档地址
版权属于:Vsunks.V
本文链接:http://blog.sunxiaowei.net/java/45.html
转载时须注明出处及本声明