Spring Boot中前端通过请求接口下载后端存放的Excel模板

导出工具类

package com.yutu.garden.utils;import com.baomidou.mybatisplus.core.toolkit.ObjectUtils;
import org.apache.commons.io.IOUtils;
import org.apache.poi.hssf.util.HSSFColor;
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.apache.poi.hssf.usermodel.*;
import org.apache.poi.ss.usermodel.*;
import org.springframework.core.io.ResourceLoader;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;import javax.annotation.Resource;
import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;/*** @ClassName: ExcelUtils* @Description: Excel相关操作* @Author* @Date 2022/4/11* @Version 1.0*/
@Component
public class ExcelUtils {@Resourceprivate  ResourceLoader resourceLoader;private static Logger log = LoggerFactory.getLogger(ExcelUtils.class);static{System.setProperty("java.awt.headless", "true");}/*** 设置表头* @param sheet sheet* @param str 表头数据* @param startNum 开始行* @param height 高度* @param style 样式*/public static void setTitle(HSSFSheet sheet, String[] str,int startNum,Short height,HSSFCellStyle style,Integer[] widths,int width) {try {HSSFRow row = sheet.createRow(startNum);if(ObjectUtils.isEmpty(height)){height = (short)(20*20);}row.setHeight(height);//创建表头名称HSSFCell cell;for (int j = 0; j < str.length; j++) {cell = row.createCell(j);//设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度if(ObjectUtils.isNotEmpty(widths) && ObjectUtils.isNotEmpty(widths[j]) ){sheet.setColumnWidth(j, widths[j]);}else{sheet.autoSizeColumn(j);int colWidth = sheet.getColumnWidth(j) * width / 10;
//					if (colWidth > 255) {
//						colWidth = 255;
//					}sheet.setColumnWidth(j, colWidth);}cell.setCellValue(str[j]);cell.setCellStyle(style);}} catch (Exception e) {e.printStackTrace();}}public static void setTitle(HSSFSheet sheet, List<String> str,int startNum,Short height,HSSFCellStyle style,Integer[] widths) {try {HSSFRow row = sheet.createRow(startNum);if(ObjectUtils.isEmpty(height)){height = (short)(20*20);}row.setHeight(height);//创建表头名称HSSFCell cell;for (int j = 0; j < str.size(); j++) {cell = row.createCell(j);//设置列宽,setColumnWidth的第二个参数要乘以256,这个参数的单位是1/256个字符宽度if(ObjectUtils.isNotEmpty(widths) && ObjectUtils.isNotEmpty(widths[j]) ){sheet.setColumnWidth(j, widths[j]);}else{sheet.autoSizeColumn(j);sheet.setColumnWidth(j, sheet.getColumnWidth(j) * 30 / 10);}cell.setCellValue(str.get(j));cell.setCellStyle(style);}} catch (Exception e) {e.printStackTrace();}}/*** 方法名:setData* 功能:表格赋值*/public static void setData(HSSFSheet sheet, List<Object[]> data,int startNum,HSSFCellStyle style) {try{int rowNum = startNum+1;for (int i = 0; i < data.size(); i++) {HSSFRow row = sheet.createRow(rowNum);for (int j = 0; j < data.get(i).length; j++) {HSSFCell cell = row.createCell(j);if(ObjectUtils.isEmpty(data.get(i)[j])){cell.setCellValue("");}else{cell.setCellValue(data.get(i)[j].toString());}cell.setCellStyle(style);}rowNum++;}}catch (Exception e){e.printStackTrace();}}public static void setDataByList(HSSFSheet sheet, List<List<Object>> data,int startNum) {try{int rowNum = startNum+1;for (int i = 0; i < data.size(); i++) {HSSFRow row = sheet.createRow(rowNum);for (int j = 0; j < data.get(i).size(); j++) {if(ObjectUtils.isEmpty(data.get(i).get(j))){row.createCell(j).setCellValue("");}else{row.createCell(j).setCellValue(data.get(i).get(j).toString());}}rowNum++;}}catch (Exception e){e.printStackTrace();}}/*** 方法名:setBrowser* 功能:使用浏览器下载*/public static void setBrowser(HttpServletResponse response, HSSFWorkbook workbook, String fileName) {try {//清空response//response.reset();//设置response的HeaderString name = URLEncoder.encode(fileName, "UTF-8");//Content-disposition 的 attachment参数将文件作为附件下载//response.setHeader("Content-disposition", "attachment;filename=" + fileName+".xlsx");response.setHeader( "Content-Disposition", "attachment;filename=\"" + name + "\".xlsx;filename*=utf-8''" + name +".xlsx");OutputStream os = new BufferedOutputStream(response.getOutputStream());response.setContentType("application/vnd.ms-excel");response.setCharacterEncoding("utf-8");//将excel写入到输出流中workbook.write(os);os.flush();os.close();} catch (Exception e) {e.printStackTrace();}}/*** 居中* @param workbook* @return*/public static HSSFCellStyle getStyleByCENTER(HSSFWorkbook workbook,int size){//设置标题样式HSSFCellStyle style = workbook.createCellStyle();HSSFFont font = workbook.createFont();font.setBold(true);font.setFontName("宋体");font.setFontHeightInPoints((short) size);style.setFont(font);//水平居中style.setAlignment(HorizontalAlignment.CENTER);//垂直居中style.setVerticalAlignment(VerticalAlignment.CENTER);style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));return style;}/*** 带边框的样式* @param workbook workbook* @param size 字体大小* @param isText 是否正文* @return*/public static HSSFCellStyle getStyleByBorder(HSSFWorkbook workbook,int size,boolean isText){//设置标题样式HSSFCellStyle style = workbook.createCellStyle();HSSFFont font = workbook.createFont();if(!isText){font.setBold(true);}font.setFontName("宋体");font.setFontHeightInPoints((short) size);style.setFont(font);//水平居中style.setAlignment(HorizontalAlignment.CENTER);//垂直居中style.setVerticalAlignment(VerticalAlignment.CENTER);style.setDataFormat(HSSFDataFormat.getBuiltinFormat("m/d/yy h:mm"));//边框style.setBorderBottom(BorderStyle.THIN);style.setBorderLeft(BorderStyle.THIN);style.setBorderTop(BorderStyle.THIN);style.setBorderRight(BorderStyle.THIN);return style;}public static HSSFCellStyle getDataStyle(HSSFWorkbook workbook,int size,boolean isSetBold,HSSFColor.HSSFColorPredefined background){//设置标题样式HSSFCellStyle style = workbook.createCellStyle();HSSFFont font = workbook.createFont();font.setBold(isSetBold);font.setFontName("宋体");font.setFontHeightInPoints((short) size);style.setFont(font);if(ObjectUtils.isNotEmpty(background)){//设置填充方式style.setFillPattern(FillPatternType.SOLID_FOREGROUND);style.setFillForegroundColor(background.getIndex());}return style;}/*** 解析上传的excel, 默认只解析第一张Sheet** @param file     excel* @param startRow 数据开始行* @return List<String [ ]>* @throws IOException*/public static List<String> getExcelData(MultipartFile file, int startRow, Integer endRow){int resultSize = 0;ArrayList<String> resultData = new ArrayList<>(resultSize);try {if (!checkFile(file)) {log.error("上传的excel文件格式有问题");return resultData;}//获得Workbook工作薄对象Workbook workbook = getWorkBook(file);if (ObjectUtils.isNotEmpty(workbook)) {//获取第一张sheet工作表Sheet sheet = workbook.getSheetAt(0);if (ObjectUtils.isEmpty(sheet)) {return resultData;}// 重新初始化List结果大小resultSize = sheet.getLastRowNum() + 1;//获得当前sheet的开始行int firstRowNum = sheet.getFirstRowNum();//获得当前sheet的结束行int lastRowNum = sheet.getLastRowNum();if(ObjectUtils.isNotEmpty(endRow)){lastRowNum = endRow;}//循环除了startRow的所有行,如果要循环除第一行以外的就firstRowNum+1for (int rowNum = firstRowNum + startRow; rowNum <= lastRowNum; rowNum++) {//获得当前行Row row = sheet.getRow(rowNum);if (rowIsEmpty(row)) {break;}//获得当前行的开始列int firstCellNum = row.getFirstCellNum();//获得当前行的列数int lastCellNum = row.getLastCellNum();//String[] cells = new String[lastCellNum];StringBuilder stringBuffer = new StringBuilder();//循环当前行for (int cellNum = firstCellNum; cellNum < lastCellNum; cellNum++) {Cell cell = row.getCell(cellNum);//cells[cellNum] = getCellValue(cell);String cellValue = getCellValue(cell);stringBuffer.append(getCellValue(cell)).append(",&");//加个&防止有答案中有,的}//resultData.add(cells);resultData.add(stringBuffer.toString());}workbook.close();}} catch (IOException e) {e.printStackTrace();}return resultData;}/*** 检查文件格式** @param file* @throws IOException*/public static boolean checkFile(MultipartFile file) throws IOException {if (null == file) {log.error("文件不存在!");return false;}//获得文件名String fileName = file.getOriginalFilename();//判断文件是否是excel文件if (ObjectUtils.isEmpty(fileName) || (!fileName.endsWith("xls") && !fileName.endsWith("xlsx"))) {log.error(fileName + "不是excel文件");return false;}return true;}/*** 获取工作簿对象** @param file* @return*/public static Workbook getWorkBook(MultipartFile file) {//获得文件名String fileName = file.getOriginalFilename();//创建Workbook工作薄对象,表示整个excelWorkbook workbook = null;try {//获取excel文件的io流InputStream is = file.getInputStream();//根据文件后缀名不同(xls和xlsx)获得不同的Workbook实现类对象if(ObjectUtils.isNotEmpty(fileName)){if (fileName.endsWith("xls")) {//2003workbook = new HSSFWorkbook(is);} else if (fileName.endsWith("xlsx")) {//2007 及2007以上workbook = new XSSFWorkbook(is);}}} catch (IOException e) {log.error(e.getMessage());}return workbook;}public static String getCellValue(Cell cell) {String cellValue = "";if (cell == null) {return cellValue;}switch (cell.getCellTypeEnum()) {case NUMERIC://数字cellValue = stringDateProcess(cell);break;case STRING://字符串cellValue = String.valueOf(cell.getStringCellValue());break;case BOOLEAN://BooleancellValue = String.valueOf(cell.getBooleanCellValue());break;case FORMULA://公式cellValue = String.valueOf(cell.getCellFormula());break;case BLANK://空值cellValue = "";break;case ERROR://故障cellValue = "非法字符";break;default:cellValue = "未知类型";break;}return cellValue;}public static String stringDateProcess(Cell cell) {String result = new String();if (HSSFDateUtil.isCellDateFormatted(cell)) {// 处理日期格式、时间格式SimpleDateFormat sdf = null;if (cell.getCellStyle().getDataFormat() == HSSFDataFormat.getBuiltinFormat("h:mm")) {sdf = new SimpleDateFormat("HH:mm");} else {// 日期sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");}Date date = cell.getDateCellValue();result = sdf.format(date);} else if (cell.getCellStyle().getDataFormat() == 58) {// 处理自定义日期格式:m月d日(通过判断单元格的格式id解决,id的值是58)SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd hh:mm:ss");double value = cell.getNumericCellValue();Date date = org.apache.poi.ss.usermodel.DateUtil.getJavaDate(value);result = sdf.format(date);} else {double value = cell.getNumericCellValue();CellStyle style = cell.getCellStyle();DecimalFormat format = new DecimalFormat();String temp = style.getDataFormatString();// 单元格设置成常规if ("General".equals(temp)) {int decimalPlaces = countDecimalPlaces(value);StringBuilder pattern = new StringBuilder("#.");for (int i = 0; i < decimalPlaces; i++) {pattern.append("#");}format.applyPattern(pattern.toString());}result = format.format(value);}return result;}public static int countDecimalPlaces(double value) {String stringValue = Double.toString(value);int integerPlaces = stringValue.indexOf('.');return stringValue.length() - integerPlaces - 1;}/*** @return * @param null* @Author* @Description //TODO 判断excel的row是否全为空* @Date 2019/12/2 19:30* @Param*/public static boolean rowIsEmpty(Row row) {if (null == row) {return true;}for (int c = row.getFirstCellNum(); c < row.getLastCellNum(); c++) {Cell cell = row.getCell(c);if (cell != null && cell.getCellTypeEnum() != CellType.BLANK) {return false;}}return true;}/*** 模板下载* @param response* @param request* @param filename* @param path* @throws IOException*/public void downloadTemplate(HttpServletResponse response, HttpServletRequest request, String filename, String path) throws IOException {InputStream inputStream = null;ServletOutputStream servletOutputStream = null;try {org.springframework.core.io.Resource resource = resourceLoader.getResource("classpath:" + path);response.setContentType("application/vnd.ms-excel");response.addHeader("Cache-Control", "no-cache, no-store, must-revalidate");response.addHeader("charset", "utf-8");response.addHeader("Pragma", "no-cache");String encodeName = URLEncoder.encode(filename, StandardCharsets.UTF_8.toString());response.setHeader("Content-Disposition", "attachment; filename=\"" + encodeName + "\"; filename*=utf-8''" + encodeName);inputStream = resource.getInputStream();servletOutputStream = response.getOutputStream();IOUtils.copy(inputStream, servletOutputStream);response.flushBuffer();} catch (Exception e) {e.printStackTrace();} finally {try {if (servletOutputStream != null) {servletOutputStream.close();}if (inputStream != null) {inputStream.close();}// jvm的垃圾回收System.gc();} catch (Exception e) {e.printStackTrace();}}}
}

控制层接口

package com.yutu.garden.controller;import com.yutu.garden.utils.ExcelUtilsWP;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;@RestController
@RequestMapping("excel")
@Api(tags = "Excel模板下载")
public class ExcelTemplateController {@Resourceprivate ExcelUtilsWP excelUtils;@ApiOperation("下载苗木计划清单模板")@GetMapping("/downloadPunishTemplate")public void downloadPunishTemplate(HttpServletResponse response, HttpServletRequest request) throws IOException {String filename = "苗木计划清单模板.xlsx";String path = "template/苗木计划清单模板.xlsx";excelUtils.downloadTemplate(response,request,filename,path);}
}

Excel模板存放位置

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/790457.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

云计算的安全需求

目录 一、概述 二、云安全服务基本能力要求 三、信息安全服务&#xff08;云计算安全类&#xff09;资质要求 3.1 概述 3.2 资质要求内容 3.2.1 组织与管理要求 3.2.2 技术能力要求 四、云安全主要合规要求 4.1 安全管理机构部门的建立 4.2 安全管理规范计划的编制 4…

C++ //练习 11.3 编写你自己的单词计数程序。

C Primer&#xff08;第5版&#xff09; 练习 11.3 练习 11.3 编写你自己的单词计数程序。 环境&#xff1a;Linux Ubuntu&#xff08;云服务器&#xff09; 工具&#xff1a;vim 代码块 /*************************************************************************> …

2024最新AI创作系统ChatGPT源码+Ai绘画网站源码,GPTs应用、AI换脸、插件系统、GPT文档分析、GPT语音对话一站式解决方案

一、前言 SparkAi创作系统是基于ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统&#xff0c;支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美&#xff0c;那么如何搭建部署AI创作ChatGPT&#xff1f;小编这里写一个详细图文教程吧。已支持GPT…

记 log4j-over-slf4j.jar AND bound slf4j-log4j12.jar jar包冲突问题

报错信息如下 SLF4J: Detected both log4j-over-slf4j.jar AND bound slf4j-log4j12.jar on the class path, preempting StackOverflowError. SLF4J: See also http://www.slf4j.org/codes.html#log4jDelegationLoop for more details. Exception in thread “main” java.lan…

NineData云原生智能数据管理平台新功能发布|2024年3月版

数据库 DevOps - 大功能升级 SQL 开发早期主要提供 SQL 窗口&#xff08;IDE&#xff09;功能&#xff0c;在产品经过将近两年时间的打磨&#xff0c;新增了大量的企业级功能&#xff0c;已经服务了上万开发者&#xff0c;覆盖了数据库设计、开发、测试、变更等生命周期的功能…

神经网络与深度学习(二)

一、深度学习平台 张量&#xff08;Tensor&#xff09; 是一个物理量&#xff0c;对高维(维数 ≥ 2) 的物理量进行“量纲分析” 的一种工具。简单的可以理解为&#xff1a;一维数组称为矢量&#xff0c;二维数组为二阶张量&#xff0c;三维数组为三阶张量 计算图 用“结点”…

调用飞书获取用户Id接口成功,但是没有返回相应数据

原因&#xff1a; 该自建应用没有开放相应的数据权限。 解决办法&#xff1a; 在此处配置即可。

DETR【Transformer+目标检测】

End-to-End Object Detection with Transformers 2024 NVIDIA GTC&#xff0c;发布了地表最强的GPU B200&#xff0c;同时&#xff0c;黄仁勋对谈《Attention is All You Need》论文其中的7位作者&#xff0c;座谈的目的无非就是诉说&#xff0c;Transformer才是今天人工智能成…

【环境变量】命令行参数 | 概念 | 理解 | 命令行参数表 | bash进程

目录 四组概念 命令行参数概念&理解 查看命令函参数 命令行字符串&命令行参数表 命令行参数存在的意义 谁形成的命令行参数 父进程&子进程&数据段 bash进程 最近有点小忙&#xff0c;可能更新比较慢。 四组概念 竞争性: 系统进程数目众多&#xff0c…

构建企业级微服务平台:实现可扩展性、弹性和高效性

在软件开发的快速发展领域中&#xff0c;企业不断努力构建健壮、可扩展和高效的系统。随着微服务架构的出现&#xff0c;再加上云原生技术的应用&#xff0c;创建敏捷且具有弹性的平台的可能性是无限的。在本指南中&#xff0c;我们将深入探讨使用强大的工具和技术组合&#xf…

Python基于深度学习的人脸识别项目源码+演示视频,利用OpenCV进行人脸检测与识别 preview

​ 一、原理介绍 该人脸识别实例是一个基于深度学习和计算机视觉技术的应用&#xff0c;主要利用OpenCV和Python作为开发工具。系统采用了一系列算法和技术&#xff0c;其中包括以下几个关键步骤&#xff1a; 图像预处理&#xff1a;首先&#xff0c;对输入图像进行预处理&am…

.Net Core/.Net6/.Net8 ,启动配置/Program.cs 配置

.Net Core/.Net6/.Net8 &#xff0c;启动配置/Program.cs 配置 没有废话&#xff0c;直接上代码调用 没有废话&#xff0c;直接上代码 /// <summary>/// 启动类/// </summary>public static class Mains{static IServiceCollection _services;static IMvcBuilder _…

Debian linux版本下运行的openmediavault网盘 千兆网卡升级万兆

一、适用场景 1、使用vmware ESXi虚拟化平台运行多种不同应用服务器时&#xff0c;其中网盘服务器采用开源的openmediavault搭建&#xff1b; 2、将老专业服务器升级千兆网为万兆网&#xff1b; 3、需要转移的数据量大的企业或用户&#xff1b; 4、从服务器到服务器的数据转移…

【群晖】NASTOOL-自动化处理影音视频工具

【群晖】NASTOOL-自动化处理影音视频 本文主要从获取、部署、使用、配置等方面进行手把手教学如何使用nastool工具进行影音视频自动化处理。从此靠别繁琐的网上各个网址找资源-下载-复制-改名-刮削等操作。 准备 DSM 7.1 &#xff08;我使用的是群晖 7.1 系统&#xff0c;不管…

实战webSocket压测(二)jmeter配置webSocket连接

背景 我们可以通过Jmeter添加插件实现webSocket脚本编写。WebSocket的插件较多&#xff0c;我选择以WebSocket Samplers by Peter Doornbosch为例来进行配置。 步骤1、WebSocket Samplers插件安装 下载地址&#xff1a;JMeter WebSocket Samplers&#xff0c;建议下载最新版本…

Termius for Mac v8.4.0激活版下载

Termius for Mac是一款功能强大的多协议远程管理软件&#xff0c;专为开发人员、系统管理员和网络专业人士设计。它支持多种远程连接协议&#xff0c;如SSH、Telnet、RDP、VNC和RFB等&#xff0c;使得用户可以轻松连接到不同类型的远程服务器和设备。 软件下载&#xff1a;Term…

智慧展览馆:基于AI智能识别技术的视频智慧监管解决方案

一、建设背景 随着科技的不断进步和社会安全需求的日益增长&#xff0c;展览馆作为展示文化、艺术和科技成果的重要场所&#xff0c;其安全监控系统的智能化升级已成为当务之急。为此&#xff0c;旭帆科技&#xff08;TSINGSEE青犀&#xff09;基于视频智能分析技术推出了展览馆…

[C++初阶]初识C++(一)—————命名空间和缺省函数

声明: 本篇文献内容选自百度文库、比特就业课 代码内容部分选自比特就业课 一、命名空间 1.什么是命名空间 在编程语言中&#xff0c;命名空间是一种特殊的作用域&#xff0c;它包含了处于该作用域中的所有标示符&#xff0c;而且其本身也是由标示符表示的。命名空间的使用目…

STM32的定时器中断Cubemx

STM32的定时器中断Cubemx 0.定时器简介1.配置时钟2.配置定时器3.创建工程4.补充源码 0.定时器简介 基本定时器功能&#xff1a; 16位向上、向下、向上/下自动装载计数器16位可编程(可以实时修改)预分频器&#xff0c;计数器时钟频率的分频系数为1&#xff5e;65535之间的任意…

vue2源码解析——vue中如何进行依赖收集、响应式原理

vue每个组件实例vm都有一个渲染watcher。每个响应式对象的属性key都有一个dep对象。所谓的依赖收集&#xff0c;就是让每个属性记住它依赖的watcher。但是属性可能用在多个模板里&#xff0c;所以&#xff0c;一个属性可能对应多个watcher。因此&#xff0c;在vue2中&#xff0…