# SpringBoot集成文件
# 基础的文件上传与下载
# 引入依赖
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
# yml配置
spring:
servlet:
multipart:
max-file-size: 10MB # 单个文件大小
max-request-size: 500MB # 总文件大小
# 使用
文件长传
@PostMapping("/upload")
public ResponseResult<String> upload(@RequestParam(value="file",required = true) MultipartFile file){
try {
String uploadPath = "d:/upload";
File uploadDir = new File(uploadPath);
if(!uploadDir.exists()){
uploadDir.mkdir();
}
log.info(uploadDir.getAbsolutePath());
// new一个本地文件
File localFile = new File(uploadPath + File.separator + file.getOriginalFilename());
// 保存到本地
file.transferTo(localFile);
} catch (Exception e) {
e.printStackTrace();
return ResponseResult.fail(e.getMessage());
}
return ResponseResult.success();
}
文件下载
@GetMapping("/download")
public void download(HttpServletResponse response){
response.reset(); // 清除任何已设置的内容和头部信息
response.setContentType("application/octet-stream");// 通用的二进制流
// Content-disposition 指示如何处理接收到的响应内容
// 接受的内容为一个附件,触发浏览器下载,指定文件名
response.setHeader("Content-disposition",
"attachment;filename=file_"+System.currentTimeMillis()+".pdf");
File file = new File("d:download/毛泽东选集.pdf");
// 建立输入流
try (FileInputStream inputStream = new FileInputStream(file)){
byte[] b = new byte[1024]; // 临时存储输入流中的数据
int len;
while((len = inputStream.read(b))>0){
response.getOutputStream().write(b,0,len);
}
} catch (IOException e) {
e.printStackTrace();
}
}
原文链接 https://www.pdai.tech/md/spring/springboot/springboot-x-file-upload-download.html
# 大文件上传(补充)
# 基于分片的断点续传和秒传
- 分片上传:大文件分成若干份大小相等的小文件,等所有小文件上传成功后再合并成完整的原始文件
- 断点续传:重新上传文件时先判断那些文件已经上传过了,如果上传过了跳过这些块,否则则上传
- 秒传:检测是否已经上传过了
前后端分工?
- 前端:file.slice()分成多个文件,并计算md5值
- 后端,许接受每次上传的文件块并保存文件块信息,所有文件块上传完毕,合并为大文件
异步上传:
@EnableAsync 用在Springboot启动类上
@Async 用在方法上
# Excel文件上传下载
# 集成POI
# 引入依赖
- poi支持xls、poi-ooxml支持xlsx文件
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>5.2.2</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>5.2.2</version>
</dependency>
# 使用
- controller
@ApiOperation("下载Excel")
@GetMapping("/excel/download")
public void download(HttpServletResponse response){
try {
SXSSFWorkbook workbook = userService.generateExcelWorkbook();
response.reset();
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-disposition","attachment;filename=user_excel_" + System.currentTimeMillis() + ".xlsx");
ServletOutputStream os = response.getOutputStream();
workbook.write(os);
workbook.dispose();
} catch (Exception e) {
e.printStackTrace();
}
}
- service
/**
* 生成工作文件
* @return
*/
@Override
public SXSSFWorkbook generateExcelWorkbook() {
SXSSFWorkbook workbook = new SXSSFWorkbook();
Sheet sheet = workbook.createSheet();
int rows = POSITION_ROW;
int cols = POSITION_COL;
// 表头
Row head = sheet.createRow(rows++);
String[] cloumns = new String[]{"ID", "Name", "Email", "Phone", "Description"};
int[] colWidths = new int[]{2000, 3000, 5000, 5000, 8000};
CellStyle headStyle = getHeadCellStyle(workbook);
for(int i=0;i<cloumns.length;i++){
sheet.setColumnWidth(cols,colWidths[i]);
addCellWithStyle(head, cols++, headStyle).setCellValue(cloumns[i]);
}
// 表内容
CellStyle bodyStyle = getBodyCellStyle(workbook);
for(User user : getUserList()){
cols = POSITION_COL;
Row row = sheet.createRow(rows++);
addCellWithStyle(row,cols++,bodyStyle).setCellValue(user.getId());
addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getUserName());
addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getEmail());
addCellWithStyle(row, cols++, bodyStyle).setCellValue(String.valueOf(user.getPhoneNumber()));
addCellWithStyle(row, cols++, bodyStyle).setCellValue(user.getDescription());
}
return workbook;
}
# 集成EasyExcel
阿里开源的基于POI封装的EXCEL处理库,使用了缓冲区,降低读取excel文件时使用的内存
# 引入依赖
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>easyexcel</artifactId>
<version>3.1.1</version>
</dependency>
# 读excel
读取excel代码
@Test
public void testRead(){
File file = new File("e:\\查询船舶.csv");
EasyExcel.read(file, Ship.class, new ShipReadListener())
.sheet()
.doRead();
}
实体类Ship
@Getter
@Setter
@EqualsAndHashCode
public class Ship {
@ColumnWidth(15) // 列宽
@ExcelProperty("fLong") // 列名
private double lon;
@ColumnWidth(15)
@ExcelProperty("fLat")
private double lat;
@ColumnWidth(20)
@DateTimeFormat("yyyy/MM/dd HH:mm")
@ExcelProperty(index = 2)
private String date;
@Override
public String toString() {
return "Ship{" +
"lon=" + lon +
", lat=" + lat +
", date='" + date + '\'' +
'}';
}
}
自定义读监听器
/**
* 自定义读监听器,需要实现ReadListener接口
*/
public class ShipReadListener implements ReadListener<Ship> {
/**
* 每隔5条存储数据库,实际使用中可以100条,然后清理list ,方便内存回收
*/
public static final int BATCH_COUNT = 5;
/**
* 缓存的数据
*/
private List<Ship> cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
/**
* 每一条数据解析都会调用
* @param ship excel数据对象
* @param analysisContext
*/
@Override
public void invoke(Ship ship, AnalysisContext analysisContext) {
//System.out.println(ship.toString());
cachedDataList.add(ship);
if(cachedDataList.size() >= BATCH_COUNT){
cachedDataList = ListUtils.newArrayListWithExpectedSize(BATCH_COUNT);
System.out.println("清空缓存");
}
}
/**
* 全部解析完成,把剩下的存入数据库
* @param context
*/
@Override
public void doAfterAllAnalysed(AnalysisContext context) {
System.out.println("存储数据库成功");
}
}
# 写excel
@Test
public void testWrite(){
File file = new File("e:\\船舶模拟数据.xlsx");
// 忽略某些列
HashSet<String> excludeColumns = new HashSet<String>();
//excludeColumns.add("lon");
EasyExcel.write(file, Ship.class)
.excludeColumnFieldNames(excludeColumns)
.sheet("船舶模拟数据")
.doWrite(getData());
}
mock数据
// 生成数据
private List<Ship> getData(){
List<Ship> list = ListUtils.newArrayList();
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/MM/dd HH:mm");
for (int i = 0; i < 100; i++) {
Ship ship = new Ship();
ship.setLon(117.894562 + Math.random());
ship.setLat(36.985712 + Math.random());
ship.setDate(LocalDateTime.now().format(formatter));
list.add(ship);
}
return list;
}
# web写
在web中写入也很简单,只需要定义实体类,标注类名,字段格式
@GetMapping("/download")
public void download(HttpServletResponse response) throws IOException {
// 指定响应内容为xlsx格式
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setCharacterEncoding("utf-8");
// 防止中文乱码
String fileName = URLEncoder.encode("测试", "UTF-8").replaceAll("\\+", "%20");
// 告诉浏览器这是一个应该立即下载的文件,并且指定文件名
response.setHeader("Content-Disposition", "attachment;filename*=utf-8''" + fileName + ".xlsx");
EasyExcel.write(response.getOutputStream(), User.class).sheet("模板").doWrite(data());
}
private List<User> data() {
List<User> list = new ArrayList<>();
for (int i = 0; i < 100; i++) {
User user = new User();
user.setName("theonefx" + i);
user.setAge(i);
list.add(user);
}
return list;
}
访问http://localhost:8080/download