java poi Exce加密l文件导出和下载

1.前言

在写系统软件里, 系统要导出数据是一个很频繁,也很普遍的需求.所以我特此记录下,前几天我写的导出,方便以后用到,或者能帮助到有需要的人。 感谢.

我这里只能用于少量数据导出(大概五万条,最多十万,具体没去测试…),大数据到的话 可能造成内存 “爆炸…”, 你要大数据导出也可以,我的想法是牺牲性能,分页导出。循环调用分页查询接口然后再将查询出的数据导出…,具体请根据自己需求。

前段时间公司忙,一直有开发任务在身上,所以没写博客,最近有时间写个博客好好沉淀一下 哈哈.也方便日后拿起就用…

2.准备工作说明

我这里虽然是springboot,maven.但mapper.xml, mapper, service, serviceImpl我就不写了,只写关键部分.

思路说明:
1.连接数据库
2.点击查询
3.将查询出的数据调用生成excel各列
4.生成文件
5.返回给前端文件名称
6.前端收到请求成功后拿到文件名称
7.根据文件名称去目录下下载

3.导出功能所依赖的jar包

<dependency>
	<groupId>org.apache.poi</groupId>
	<artifactId>poi</artifactId>
	<version>3.15</version>
</dependency>
<dependency>
    <groupId>org.apache.poi</groupId>
    <artifactId>poi-ooxml</artifactId>
    <version>3.15</version>
</dependency>

4.撸代码异常状态码类(ErrorCode)

	package com.test.error;

public enum ErrorCode {
	ERROR_SUCCESS(0, "成功"),						
	ERROR_SERVER_ERROR(-500, "服务内部错误"),		
	ERROR_BUSY(-429, "系统繁忙,请稍后重试"),
	ERROR_NOT_FOUND(-1, "未找到或不存在"),								
	ERROR_HANDLE_TIMEOUT(-2, "超时"),	
	ERROR_INVALID_PARAM(-3, "无效参数"),			
	ERROR_CHECK_CODE(-4, "验证码错误或已失效"),
	ERROR_MEMORY_OUT(-5, "内存溢出"),		
	ERROR_OBJECT_EXIST(-6, "对象已存在"),
	ERROR_USER_PASSWORD(-7, "用户名或密码不正确"),
	ERROR_DELETE_FAIL(-8, "删除对象失败"),
	ERROR_INVALID_ARRAY(-9, "无效列表"),
	ERROR_EXIST_TIMESPAN(-10, "该时间段包含已有时间"),
	ERROR_NOT_LOGIN(-10, "未登录或会话过期"),
	ERROR_NOT_SUPPORT(-11, "接口不支持"),
	ERROR_NO_RIGHT(-12, "权限不足"),
	ERROR_NOT_AVAILABLE(-13, "服务暂不可用"),
	ERROR_USER_HAS_LOGIN(-14, "用户已登录"),
	ERROR_WRITE_FAILED(-41, "写文件失败"),
	ERROR_READ_FAILED(-42, "读文件失败"),
	ERROR_UPLOAD_FAILED(-43, "上传文件失败"),
	ERROR_UNKNOW(-50, "未知错误"),
	ERROR_REGION_LIMIT(-51, "区域已经达到最大个数")
	;		
	
	private Integer error;	
	private String description;	
	
	private ErrorCode(Integer error, String description){
		this.error = error;
		this.description = description;
	}
	
	public Integer getError(){
		return this.error;
	}

	public String getDescription() {
		return description;
	}

	public void setDescription(String description) {
		this.description = description;
	}

	public void setError(Integer error) {
		this.error = error;
	}
	
	static public String getDescription(Integer error) {
		String desc = "";
		if(ERROR_SUCCESS.getError() == error){
			desc = ERROR_SUCCESS.getDescription();
		}
		if(ERROR_SERVER_ERROR.getError() == error){
			desc = ERROR_SERVER_ERROR.getDescription();
		}
		if(ERROR_BUSY.getError() == error){
			desc = ERROR_BUSY.getDescription();
		}
		if(ERROR_NOT_FOUND.getError() == error){
			desc = ERROR_NOT_FOUND.getDescription();
		}
		if(ERROR_HANDLE_TIMEOUT.getError() == error){
			desc = ERROR_HANDLE_TIMEOUT.getDescription();
		}
		if(ERROR_INVALID_PARAM.getError() == error){
			desc = ERROR_INVALID_PARAM.getDescription();
		}								
		if(ERROR_CHECK_CODE.getError() == error){
			desc = ERROR_CHECK_CODE.getDescription();
		}								
		if(ERROR_MEMORY_OUT.getError() == error){
			desc = ERROR_MEMORY_OUT.getDescription();
		}								
		if(ERROR_OBJECT_EXIST.getError() == error){
			desc = ERROR_OBJECT_EXIST.getDescription();
		}
		if(ERROR_USER_PASSWORD.getError() == error){
			desc = ERROR_USER_PASSWORD.getDescription();
		}
		if(ERROR_DELETE_FAIL.getError() == error){
			desc = ERROR_DELETE_FAIL.getDescription();
		}
		if(ERROR_INVALID_ARRAY.getError() == error){
			desc = ERROR_INVALID_ARRAY.getDescription();
		}
		if(ERROR_EXIST_TIMESPAN.getError() == error){
			desc = ERROR_EXIST_TIMESPAN.getDescription();
		}
		if(ERROR_NOT_LOGIN.getError() == error){
			desc = ERROR_NOT_LOGIN.getDescription();
		}
		if(ERROR_NOT_SUPPORT.getError() == error){
			desc = ERROR_NOT_SUPPORT.getDescription();
		}
		if(ERROR_NO_RIGHT.getError() == error){
			desc = ERROR_NO_RIGHT.getDescription();
		}
		if(ERROR_NOT_AVAILABLE.getError() == error){
			desc = ERROR_NOT_AVAILABLE.getDescription();
		}
		return desc;
	}
}

5.撸代码异常类(DCPException类)

package com.test.exception;

import com.dondown.error.ErrorCode;

import lombok.Data;


@Data
public class DCPException extends Exception{

	private static final long serialVersionUID = 1L;
	private	ErrorCode errorCode;
	
	public DCPException(ErrorCode code,String  msg){
		super(msg);
		errorCode = code;
	}
}

6.返回前端提示类(ReturnValue)

package com.test.error;

import java.io.IOException;

import com.fasterxml.jackson.annotation.JsonInclude;
import com.fasterxml.jackson.annotation.JsonInclude.Include;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;

@JsonInclude(Include.NON_NULL) 
public class ReturnValue<T> {
	private Integer error = 0;				// 错误
	private String description = "";		// 错误描述
	private T value;						// 返回值【当error为ERROR_NO_SUCCESS才有可能返回值-判断值是否为空】
	
	
	// 成功不带返回值
	public ReturnValue(){
		this.error = ErrorCode.ERROR_SUCCESS.getError();
		this.description = "成功";
	}
	
	// 成功带返回值
	public ReturnValue(T value){
		if(null == value){
			this.error = ErrorCode.ERROR_NOT_FOUND.getError();
			this.description = "没有找到你需要的资源";
		} else {
			this.error = ErrorCode.ERROR_SUCCESS.getError();
			this.description = "成功";
			this.value = value;
		}		
	}
	
	// 返回错误
	public ReturnValue(ErrorCode error){
		this.error = error.getError();
		this.description = error.getDescription();
	}
	
	// 返回错误--对错误描述进行更改
	public ReturnValue(ErrorCode error, String description){
		this.error = error.getError();
		this.description = description;
	}
	
	// 返回错误
	public ReturnValue(Integer error){
		this.error = error;
		this.description = ErrorCode.getDescription(error);
	}
	
	public ReturnValue(Integer error, String description){
		this.error = error;
		this.description = description;
	}
	
	public Integer getError() {
		return error;
	}
	
	public boolean success(){
		return error == ErrorCode.ERROR_SUCCESS.getError();
	}

	public void setError(Integer error) {
		this.error = error;
	}

	public String getDescription() {
		return description;
	}
	public void setDescription(String description) {
		this.description = description;
	}

	public T getValue() {
		return value;
	}

	public void setValue(T value) {
		this.value = value;
	}
	
	/**
	 * 将字符串转为json对象
	 * @return
	 */
	@SuppressWarnings("unchecked")
	public void fromJsonString(String json){
		try {
			ObjectMapper mapper = new ObjectMapper();
			ReturnValue<T> value = mapper.readValue(json, this.getClass());
			this.setError(value.getError());
			this.setDescription(value.getDescription());
			this.setValue(value.getValue());
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	/**
	 * 将本对象转为json字符串
	 * @return
	 */
	public String toJsonString(){
		String json = "";
		try {
			ObjectMapper mapper = new ObjectMapper();
			json = mapper.writeValueAsString(this);
		} catch (JsonProcessingException e) {
			e.printStackTrace();
		}
		return json;
	}
}

7.撸代码控制器层(Controller类)

注意看代码注释

@Slf4j
@RequestMapping("/test")
public class testExportController {	
	@Autowired
	private TestService testService;
	@PostMapping("/testDataExport ")
	public ReturnValue<String> testDataExport (
				@RequestParam(name = "excelName", required = true) String excelName) {
		try {
				// CheckUtil类我就不贴出来了,就是检测对象是否为空
				// 我这里假设已经有service并且已经查询成功有数据
				List<Test> rows = testService.findByAttributes(exceName); // 这只是一句假设语句
				if (CheckUtil.isNull(rows)) {
					return new ReturnValue<>(ErrorCode.ERROR_NOT_FOUND, "无数据导出");
				}
				String fileName = TestExport.export(rows, excelName);
				return new ReturnValue<>(fileName);
			} catch (Exception e) {
				log.error(e.getMessage());
				return new ReturnValue<>(ErrorCode.ERROR_SERVER_ERROR);
			}
		}
	}

8.文件资源存放地址类(FileResource)

package com.test.export;
import java.io.File;
import java.io.FileNotFoundException;

import org.springframework.util.ResourceUtils;

public class FileResource {

	public static String xls= "";
	
	static{
		try {
			
			File path = new File(ResourceUtils.getURL("classpath:").getPath());
			// 如果通过jar允许,则使用当前jar包所在路径
			if (!path.exists())
				path = new File("");
			
			path = new File(path.getAbsolutePath(), "static"+File.separator+"xls");
			if (!path.exists())
				path.mkdirs();

			xls = path.getAbsolutePath();
		} catch (FileNotFoundException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

9.撸代码逻辑层(TestExport)

public class TestExport {
	public static String export(List<Object> rows, String excelName) throws DCPException {
		HSSFWorkbook wb = new HSSFWorkbook();
		HSSFSheet sheet = wb.createSheet("poi导出");
		sheet.setDefaultRowHeight((short) (20 * 20));
		HSSFRow row = null;
		row = sheet.createRow(0);

		// 假设你的查询数据里有表头这些字段
		// 表头
		row.createCell(0).setCellValue("企业名称");
		row.createCell(1).setCellValue("联系电话");
		row.createCell(2).setCellValue("用电量");
		row.createCell(3).setCellValue("镇街");
		row.createCell(4).setCellValue("地址");
		row.createCell(5).setCellValue("用电计费起始日期");
		row.createCell(6).setCellValue("用电计费终止日期");

		JSONArray array = JSONArray.parseArray(rows);

		// 数据
		for (int i = 0; i < array.size(); i++) {
			JSONObject jsonObj = array.getJSONObject(i);
			row = sheet.createRow(i + 1);

			row.createCell(0).setCellValue(jsonObj.getString("企业名称"));
			row.createCell(1).setCellValue(jsonObj.getString("联系电话"));
			row.createCell(2).setCellValue(jsonObj.getString("用电量"));
			row.createCell(3).setCellValue(jsonObj.getString("镇街"));
			row.createCell(4).setCellValue(jsonObj.getString("地址"));
			row.createCell(5).setCellValue(jsonObj.getString("用电计费起始日期"));
			row.createCell(6).setCellValue(jsonObj.getString("用电计费终止日期"));
		}

		sheet.setColumnWidth(0, 450 * 20);
		sheet.setColumnWidth(1, 300 * 20);
		sheet.setColumnWidth(2, 150 * 20);
		sheet.setColumnWidth(3, 150 * 20);
		sheet.setColumnWidth(4, 150 * 20);
		sheet.setColumnWidth(5, 150 * 20);
		sheet.setColumnWidth(6, 150 * 20);
		
		String fileName = createFile(wb, excelName);
		return fileName;
	}
	
	private String createFile (HSSFWorkbook wb, String name) throws DCPException {
		String filePath = FileResource.xls;
	    // 生成文件
		DateFormat fm = new SimpleDateFormat("yyyMMddhhmmss");
	      String fileName = "自定义查询-"+fm.format(new Date())+".xls";
	      FileOutputStream fos=null;
			try {
				File file = new File(filePath+File.separator+fileName);
				if(!file.exists()) {
					file.createNewFile();
				}
				// 保存此XSSFWorkbook对象为xlsx文件
				workbook.write(new FileOutputStream(file));

				POIFSFileSystem fs = new POIFSFileSystem();
				EncryptionInfo info = new EncryptionInfo(EncryptionMode.standard);
				Encryptor enc = info.getEncryptor();
				// 设置密码
				enc.confirmPassword("123456");
				// 加密文件
				OPCPackage opc = OPCPackage.open(file, PackageAccess.READ_WRITE);
				java.io.OutputStream os = enc.getDataStream(fs);
				opc.save(os);
				opc.close();

				//把加密后的文件写回到流
				fos = new FileOutputStream(file);
				fs.writeFilesystem(fos);
				
				fos.flush();
			} catch (IOException e) {
				e.printStackTrace();
				throw new DCPException(ErrorCode.ERROR_SERVER_ERROR,"导出失败");
			} catch (InvalidFormatException e) {
				e.printStackTrace();
			} catch (GeneralSecurityException e) {
				e.printStackTrace();
			} finally {
				 try {
					fos.close();
					workbook.close();
				} catch (IOException e) {
					e.printStackTrace();
					throw new DCPException(ErrorCode.ERROR_SERVER_ERROR,"导出失败");
				}
			}

	      return fileName;
	   }
}

10.前端收到成功后拿到返回值文件名称

我这里只写前端部分代码,理解意思就好.

 this.$div.find('.export-btn').on('click', function () {
    let url = `http://127.0.0.1:8080/test/testExport`;
    window.ajaxAction.post(url, null, function (data) {
      window.open("http://127.0.0.1:8080/test/download/"+ data.value);
      alert('导出成功');
    }, function (data) {
      alert('导出失败'+data.description);
    });
  });

11.文件下载控制器(DownloadController)

@Slf4j
@RestController
@RequestMapping("/test")
public class TestDownload {
@GetMapping("/download/{fileName}")
    public void download(HttpServletRequest request,HttpServletResponse response, 
    @PathVariable(name="fileName", required=true) String fileName) {
 		   FileDownload.download(request,response,FileResource.xls, fileName);
    }
 }

12.文件下载

package com.test.export;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.util.ResourceUtils;

public class FileDownload {

	/*
	 *   下载文件,下载之后删除文件
	 */
	static public void download(HttpServletRequest request, HttpServletResponse response,String filePath,String fileName){
		try {
			  // 解决文件名中文乱码问题
			  String userAgent = request.getHeader("User-Agent");
			  String formFileName = fileName;
			  if (userAgent.contains("MSIE") || userAgent.contains("Trident")) {
	               formFileName = java.net.URLEncoder.encode(fileName, "UTF-8");
	           } else {
	               // 非IE浏览器的处理:
	               formFileName = new String(fileName.getBytes("UTF-8"), "ISO-8859-1");
	           }
				
			   response.setContentType("multipart/form-data");
			   response.setHeader("Content-Disposition", "attachment;filename="+formFileName);
			   
			   File file = ResourceUtils.getFile(filePath+File.separator+fileName);
			   OutputStream out = response.getOutputStream();
			   InputStream in = new FileInputStream(file);
			   int b;
			   while((b=in.read())!=-1){
			       out.write(b);
			   }
			   in.close();      
			   out.close();  
			   file.delete();
			} catch (IOException e) {
				e.printStackTrace();
		}
	}
}

13.结尾了…

好久没写博客了,结尾都不知道写啥,哎 反正最近发际线是有点后退了。 另外,祝各位兄弟姐妹们牛逼,为什么牛逼?,为什么都牛逼! 点个赞啊。

  • 1
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值