admin管理员组文章数量:1589946
- **项目背景
随着项目日新月异的变化,对数据的安全性也越来越高,特别是政府类型的项目,数据安全往往是非常重要的,最近项目中导出的文件被要求需要密码才能打开,所以写下这篇文章,特此记录一下。
文章目录
- 前言
- 一、文档
- 二、思考与实现
- 1.ModelMap方式导出
- 2.Workbook方式的导出
- 3.封装导出工具类:
- 至此,功能已完成
前言
本项目中使用的poi框架为easypoi,springboot版本为2.0.3提示:以下是本篇文章正文内容,下面案例可供参考
一、文档
easypoi使用教程1.0
二、思考与实现
1.ModelMap方式导出
代码如下(示例):
List<ExcelExportEntity> entityList = new ArrayList<>();
entityList.add(new ExcelExportEntity("乡镇", "town", 15));
entityList.add(new ExcelExportEntity("社区", "community", 15));
entityList.add(new ExcelExportEntity("姓名", "name", 15));
entityList.add(new ExcelExportEntity("手机号", "phone", 15));
entityList.add(new ExcelExportEntity("身份证号码", "idcard", 15));
entityList.add(new ExcelExportEntity("健康管理措施", "typeName", 15));
entityList.add(new ExcelExportEntity("健康管理地址", "addr", 15));
entityList.add(new ExcelExportEntity("健康管理开始时间", "startTime", 15));
entityList.add(new ExcelExportEntity("健康管理结束时间", "endTime", 15));
List<PersonImportant> dataResult = personImportantService.selectExcelList(para);
modelMap.put(MapExcelConstants.ENTITY_LIST, entityList);
modelMap.put(MapExcelConstants.MAP_LIST, dataResult);
modelMap.put(MapExcelConstants.FILE_NAME, "重点人员健康管理人员信息");
SessionUser sessionUser = ShiroUtils.getSessionUser();
String password = sessionUser.getExcelPassword();
if (StringUtils.isEmpty(password)) {
password = "123456";
}
modelMap.put(MapExcelConstants.PASSWORD, password);
modelMap.put(NormalExcelConstants.PARAMS, new ExportParams("重点人员健康管理人员信息", "重点人员健康管理人员信息", ExcelType.XSSF));
return MapExcelConstants.EASYPOI_MAP_EXCEL_VIEW;
这种方式的导出,我们看到,官方是自带了文档加密功能,只需要我们通过参数的方式传递过去就好了,所以我们不细讲。
2.Workbook方式的导出
代码如下(示例):
@KrtLog("下载导入失败数据")
@RequiresPermissions("person:personImportantDetail:excelIn")
@GetMapping("person/personImportant/downloadExcelErrorData")
public void downloadExcelErrorData(String downErrorDataKey) {
List<PersonImportantDetail> dataResult = personImportantService.getExcelErrorData(downErrorDataKey);
Workbook workbook = ExcelExportUtil.exportExcel(new ExportParams("重点人员健康管理人员信息", "重点人员健康管理人员信息", ExcelType.XSSF), PersonImportantDetail.class, dataResult);
ExportExcelUtil.exportExcel(workbook, "导入失败-重点人员健康管理人员信息", response);
}
这种方式的导出,查阅了官方文档,没看到官方的加密功能。通过阅读ModelMap方式导出的源码发现了其加密的奥秘:
通过代码我们可以发现:
ModelMap方式的导出最后是会到这个控制层,而通过源码我们可以看到,最终是在这个controller中进行导出的:
那么让我们看看这个里面究竟做了些什么事情吧!继续追踪源码,我们可以发现,具体的实现都是在一个叫out()的方法中进行的:
让我们再次深入其中,为了更好的展现,我把这部分的源码单独粘贴出来了:
public void out(Workbook workbook, String codedFileName, String password, HttpServletRequest request, HttpServletResponse response) throws Exception {
if (workbook instanceof HSSFWorkbook) {
codedFileName = codedFileName + ".xls";
} else {
codedFileName = codedFileName + ".xlsx";
}
if (password != null && !"".equals(password)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
baos.flush();
ByteArrayInputStream workbookInput = new ByteArrayInputStream(baos.toByteArray());
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword(password);
POIFSFileSystem fs = new POIFSFileSystem();
OPCPackage opc = OPCPackage.open(workbookInput);
OutputStream os = enc.getDataStream(fs);
opc.save(os);
os.close();
opc.close();
baos = new ByteArrayOutputStream();
fs.writeFilesystem(baos);
baos.flush();
response.setHeader("content-disposition", WebFilenameUtils.disposition(codedFileName));
byte[] buff = new byte[1024];
BufferedInputStream bis = null;
try {
OutputStream os = response.getOutputStream();
bis = new BufferedInputStream(new ByteArrayInputStream(baos.toByteArray()));
for(int i = bis.read(buff); i != -1; i = bis.read(buff)) {
os.write(buff, 0, buff.length);
os.flush();
}
} catch (IOException var24) {
var24.printStackTrace();
} finally {
if (bis != null) {
try {
bis.close();
} catch (IOException var23) {
var23.printStackTrace();
}
}
}
} else {
response.setHeader("content-disposition", WebFilenameUtils.disposition(codedFileName));
ServletOutputStream out = response.getOutputStream();
workbook.write(out);
out.flush();
}
}
至此,我们便发现了他的庐山真面目,我们可以参照他的源码,自己写一个导出工具类。
3.封装导出工具类:
package com.krt.common.util;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.poifs.crypt.EncryptionInfo;
import org.apache.poi.poifs.crypt.EncryptionMode;
import org.apache.poi.poifs.crypt.Encryptor;
import org.apache.poi.poifs.filesystem.POIFSFileSystem;
import org.apache.poi.ss.usermodel.Workbook;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
/**
* @author: lyp
* @Date: 2022/1/24 10:38
* @Description: excel导出工具类
*/
@Slf4j
public class ExportExcelUtil {
/**
* 导出Excel
*
* @param workbook workbook流
* @param fileName 文件名
* @param response 响应
*/
public static void exportExcel(Workbook workbook, String fileName, HttpServletResponse response) {
// 输出文件
try (OutputStream out = response.getOutputStream()) {
// 获取文件名并转码
String name = URLEncoder.encode(fileName, "UTF-8");
// 编码
response.setCharacterEncoding("UTF-8");
// 设置强制下载不打开
response.setContentType("application/force-download");
// 下载文件的默认名称
response.setHeader("Content-Disposition", "attachment;filename=" + name + ".xlsx");
// 输出表格
workbook.write(out);
} catch (IOException e) {
log.error("文件导出异常,详情如下:{}", e);
} finally {
try {
if (workbook != null) {
// 关闭输出流
workbook.close();
}
} catch (IOException e) {
log.error("文件导出关闭输出流失败,详情如下:{}", e);
}
}
}
/**
* 导出一个需要密码打开的Excel
*
* @param workbook workbook流
* @param fileName 文件名
* @param response 响应
*/
public static void exportEncryptExcel(Workbook workbook, String fileName, HttpServletResponse response, String password) throws Exception {
//
if (password != null && !"".equals(password)) {
// 文件名
fileName = fileName + ".xlsx";
// 创建一个字节数组输出流
ByteArrayOutputStream workbookOutput = new ByteArrayOutputStream();
workbook.write(workbookOutput);
workbookOutput.flush();
// 创建一个字节数组输入流
ByteArrayInputStream workbookInput = new ByteArrayInputStream(workbookOutput.toByteArray());
// 加密
EncryptionInfo info = new EncryptionInfo(EncryptionMode.agile);
Encryptor enc = info.getEncryptor();
enc.confirmPassword(password);
// 创建一个POIFS 文件系统
POIFSFileSystem poifsFileSystem = new POIFSFileSystem();
OPCPackage opc = OPCPackage.open(workbookInput);
OutputStream outputStream = enc.getDataStream(poifsFileSystem);
opc.save(outputStream);
outputStream.close();
opc.close();
workbookOutput = new ByteArrayOutputStream();
poifsFileSystem.writeFilesystem(workbookOutput);
workbookOutput.flush();
// 获取文件名并转码
String name = URLEncoder.encode(fileName, "UTF-8");
// 编码
response.setCharacterEncoding("UTF-8");
// 设置强制下载不打开
response.setContentType("application/force-download");
// 下载文件的默认名称
response.setHeader("Content-Disposition", "attachment;filename=" + name);
byte[] buff = new byte[1024];
BufferedInputStream bufferedInputStream = null;
try {
OutputStream responseOutputStream = response.getOutputStream();
bufferedInputStream = new BufferedInputStream(new ByteArrayInputStream(workbookOutput.toByteArray()));
for (int i = bufferedInputStream.read(buff); i != -1; i = bufferedInputStream.read(buff)) {
responseOutputStream.write(buff, 0, buff.length);
responseOutputStream.flush();
}
} catch (IOException e) {
log.error("文件导出失败,详情如下:{}", e);
} finally {
if (bufferedInputStream != null) {
try {
bufferedInputStream.close();
} catch (IOException e) {
log.error("文件导出关闭输出流失败,详情如下:{}", e);
}
}
}
}
}
}
至此,功能已完成
版权声明:本文标题:java基于easypoi实现对导出的excel文档加密 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/dianzi/1728074841a1144352.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论