需求背景
现在需要通过Java获取远程对象存储OSS的excel文件内容,并修改excel内容中的指定列的值后返回新的excel给用户下载。
前台页面
前台页面列表以及搜索条件相关的就不说了,这里直接步入主题,直接讲述对应按钮的功能,页面如图
我们需要讲的就是红色框中的按钮【导出(脱敏)】,对应按钮的html代码
{ title: '操作', align: 'center', formatter: function(value, row, index) { var actions = []; actions.push('<aclass="btn btn-info btn-xs ' + editFlag + '"href="javascript:void(0)"onclick="searchClueDaily(\'' + options.searchUrl + '\',\'' + row.accountTime + '\', \''+ row.clueType+'\')"><iclass="fa fa-list"></i> 查看详情</a> '); if(row.errorDetailUrl == null || row.errorDetailUrl == ''){ actions.push('<aclass="btn btn-warning btn-xs' + clueExport + '"href="javascript:void(0)"onclick="notUrlTips()"><iclass="fa fa-download"></i> 导出</a> '); }else{ actions.push('<aclass="btn btn-warning btn-xs ' + clueExport + '"href="' + row.errorDetailUrl + '"><iclass="fa fa-download"></i> 导出</a> '); actions.push('<aclass="btn btn-warning btn-xs ' + clueExport + '"href="javascript:void(0)"onclick="exportData(\'' + row.errorDetailUrl + '\')"><iclass="fa fa-download"></i> 导出(脱敏)</a> '); } return actions.join(''); } }
对应的js代码
//errorurl为远程文件路径functionexportData(errorurl) { window.location.href=prefix+"/exportData?url="+errorurl; }
其中:prefix为页面全局变量,对应controller请求路径
var prefix = ctx + "project/accountClueDetail";
errorurl对应的是数据库中查出数据的远程excel文件路径,例如这样的
String errorurl= "http://yuancheng.test.com/online_crm/export/file/2021/10/20/线索获取明细_20210926_购书未购课中级_1634677384547.xlsx";
后端逻辑实现
整体实现逻辑就是先通过http请求获取远程excel的文件流,然后读取文件流内容到Workbook,再对Workbook中对应列的值进行修改,修改完成后重新创建该列并写回到表格中,最后返回表格给前端下载。
/*** 导出线索统计明细列表*/"project:accountClueDetail:export") ("/exportData") (publicvoidexportData(Stringurl, HttpServletResponseresponse) { URLurlfile=null; HttpURLConnectionhttpUrl=null; OutputStreamout=null; try { //创建url请求对象urlfile=newURL(url); httpUrl= (HttpURLConnection) urlfile.openConnection(); httpUrl.connect(); //创建Workbook 接收HttpURLConnection返回的输入流Workbookworkbook=WorkbookFactory.create(httpUrl.getInputStream()); //获取表格的第一个sheetSheetsheetAt=workbook.getSheetAt(0); //获取sheet的行数introws=sheetAt.getPhysicalNumberOfRows(); for (inti=1; i<rows; i++) { //第0行为表头,故从第1行开始获取行数据Rowrow=sheetAt.getRow(i); //获取第3列的数据,列的计算从0来时Cellcell=row.getCell(3); //获取对应表格的值StringcellValue=cell.getStringCellValue(); if (StringUtils.isNotEmpty(cellValue)) { //脱敏处理Stringstr=desensitizeStr(cellValue); //重新创建第1行第3列表格数据并设置脱敏后的数据Cellcell1=row.createCell(3); cell1.setCellValue(str); } } response.setCharacterEncoding("UTF-8"); response.setHeader("content-type", "application/octet-stream; charset=utf-8"); //设置文件名Stringdname=""; StringexportName=url.substring(url.lastIndexOf("/")+1,url.lastIndexOf("."))+"(脱敏)"; try { //针对IE或IE为内核的浏览器if(userAgent.contains("MSIE")||userAgent.contains("Trident")) { dname=java.net.URLEncoder.encode(exportName,"UTF-8"); }else { //谷歌控制版本dname=newString(exportName.getBytes("UTF-8"),"ISO-8859-1"); } } catch (UnsupportedEncodingExceptione) { e.printStackTrace(); } //设置response响应头response.setHeader("Content-Disposition", "attachment;filename="+dname+"(脱敏).xlsx"); out=response.getOutputStream(); workbook.write(out); //System.out.println("数据导出成功");httpUrl.disconnect(); } catch (Exceptione) { e.printStackTrace(); } finally { try { if(out!=null){ out.flush(); out.close(); } } catch (IOExceptione) { e.printStackTrace(); } } } /*** 字符串 手机号 脱敏* public static final Pattern TEXT_CONRAIN_PHONE = Pattern.compile("^(.*)(1[0-9]{9})(.*)$");* @param sensitizeStr 脱敏字符串* @return*/privateStringdesensitizeStr(StringsensitizeStr){ Matchermatcher=Regex.TEXT_CONRAIN_PHONE.matcher(sensitizeStr); if( matcher.matches() ){ Stringphone=matcher.group(2); StringreplaceStr=phone.substring(0, 3) +"****"+phone.substring(7); returnphone.replace(phone, replaceStr); } returnsensitizeStr; }
到这里就完成了,最后处理后的数据