package com.uas.report.controller; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.OutputStream; import java.net.URLEncoder; import java.util.HashMap; import java.util.Map; import javax.servlet.ServletException; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Controller; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.ResponseBody; import com.uas.report.core.exception.ReportException; import com.uas.report.service.FileService; import com.uas.report.service.PrintService; import com.uas.report.util.ArrayUtils; import com.uas.report.util.FileUtils; import com.uas.report.util.ReportConstants; import com.uas.report.util.ReportUtils; import com.uas.report.util.StringUtils; /** * 报表打印 * * @author sunyj * @since 2016年8月16日 下午3:49:02 */ @Controller @RequestMapping("/print") public class PrintController { @Autowired private PrintService printService; @Autowired private FileService fileService; private static Logger logger = LoggerFactory.getLogger(PrintController.class); /** * 为UAS系统打印提供服务, 根据printType进行预览、打印、下载pdf、下载纯数据excel等操作 * * @param userName * 不为null;当前账套名称 * @param profile * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev * @param reportName * 不为null;需要导出的报表的名称,不带任何后缀(如导出采购单,即为"Purchase") * @param whereCondition * 可为null;where之后的条件(包括where) * @param otherParameters * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数; * JSON格式,数据为键值对 * @param printType * 打印类型,可为PREVIEW_PRINT_TYPE、PRINT_PRINT_TYPE、PDF_PRINT_TYPE、 * EXCEL_PRINT_TYPE * @param title * 导出为文件时的名称 * @param request * @param response */ @RequestMapping() public void print(String userName, String profile, String reportName, String whereCondition, String otherParameters, String printType, String title, HttpServletRequest request, HttpServletResponse response) { userName = userName == null ? null : userName.toUpperCase(); // printType为空,默认进入预览页 if (StringUtils.isEmpty(printType)) { printType = ReportConstants.PREVIEW_PRINT_TYPE; } // 预览或打印 if (printType.equals(ReportConstants.PREVIEW_PRINT_TYPE) || printType.equals(ReportConstants.PRINT_PRINT_TYPE)) { try { request.getRequestDispatcher("preview").forward(request, response); } catch (IOException | ServletException e) { throw new ReportException(e).setDetailedMessage(e); } } // 下载pdf、纯数据excel else if (printType.equals(ReportConstants.PDF_PRINT_TYPE)) { export(userName, profile, reportName, whereCondition, otherParameters, ReportConstants.PDF_FILE_TYPE, true, title, request, response); } // 该下载接口供UAS系统使用,应其要求,EXCEL_PRINT_TYPE只能为EXCEL(该值意思本应为下载全部数据的excel), // 导致与EXCEL_WITH_ONLY_DATA_FILE_TYPE(下载纯数据的excel)命名不相匹配 else if (printType.equals(ReportConstants.EXCEL_PRINT_TYPE)) { export(userName, profile, reportName, whereCondition, otherParameters, ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE, true, title, request, response); } // 下载word else if (printType.equals(ReportConstants.WORD_PRINT_TYPE)) { export(userName, profile, reportName, whereCondition, otherParameters, ReportConstants.WORD_FILE_TYPE, true, title, request, response); } else { throw new ReportException("printType不合法"); } } /** * 导出报表 * * @param userName * 不为null;当前账套名称 * @param profile * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev * @param reportName * 不为null;需要导出的报表的名称,不带任何后缀(如导出采购单,即为"Purchase") * @param whereCondition * 可为null;where之后的条件(包括where) * @param otherParameters * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数; * JSON格式,数据为键值对 * @param exportFileType * 报表导出的格式,默认为pdf * @param flush * 是否强制刷新pdf、xls * @param title * 导出为文件时的名称 * @param request * @param response */ @RequestMapping("/export") @ResponseBody public void export(String userName, String profile, String reportName, String whereCondition, String otherParameters, String exportFileType, Boolean flush, String title, HttpServletRequest request, HttpServletResponse response) { userName = userName == null ? null : userName.toUpperCase(); ReportUtils.checkParameters(userName, reportName); if (printService.overload(userName, profile, reportName, whereCondition, otherParameters)) { throw new ReportException("数据量过大,无法提供服务"); } String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName); if (StringUtils.isEmpty(exportFileType)) { exportFileType = ReportConstants.PDF_FILE_TYPE; } byte[] data = null; String filePath = ReportConstants.GENERATED_FILES_PATH + reportName + "/" + fileService .generateFileName(userName, profile, reportName, whereCondition, otherParameters, exportFileType); if (exportFileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) { filePath += "." + ReportConstants.EXCEL_FILE_TYPE; } else { filePath += "." + exportFileType; } File file = new File(ReportConstants.GENERATED_FILES_DIR + filePath); // 指定flush为true(强制刷新pdf、xls) // 文件无效(不存在或过期),创建 if ((flush != null && flush.booleanValue()) || !fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))) { data = printService.export(userName, profile, reportName, whereCondition, otherParameters, exportFileType); if (ArrayUtils.isEmpty(data)) { throw new ReportException("报表导出失败:" + userName + "/" + reportName + "\n"); } FileUtils.write(file.getPath(), data); } else { FileInputStream fileInputStream = null; try { fileInputStream = new FileInputStream(file); data = new byte[fileInputStream.available()]; fileInputStream.read(data); } catch (IOException e) { throw new ReportException(e).setDetailedMessage(e); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { throw new ReportException(e).setDetailedMessage(e); } } } } try { String exportFileName = title; if (StringUtils.isEmpty(exportFileName)) { exportFileName = reportName; } if (exportFileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) { exportFileName += "." + ReportConstants.EXCEL_FILE_TYPE; } else { exportFileName += "." + exportFileType; } response.setHeader("Content-Disposition", "attachment;filename=" + URLEncoder.encode(exportFileName, "UTF-8")); OutputStream outputStream = response.getOutputStream(); outputStream.write(data); outputStream.flush(); outputStream.close(); } catch (IOException e) { logger.error("浏览器重复请求!"); } } /** * 报表预览时获取pdf流 * * @param userName * 不为null;当前账套名称 * @param profile * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev * @param reportName * 不为null;需要预览的报表的名称,不带任何后缀(如预览采购单,即为"Purchase") * @param whereCondition * 可为null;where之后的条件(包括where) * @param otherParameters * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数; * JSON格式,数据为键值对 * @param pageIndex * 分页展示,当前页码,从0开始 * @param flush * 是否强制刷新pdf、xls * @param request * @param response * @return 包括pageSize、pdfPath */ @RequestMapping(value = "/loadPdfData") @ResponseBody public Map loadPdfData(String userName, final String profile, final String reportName, final String whereCondition, final String otherParameters, Integer pageIndex, Boolean flush, HttpServletRequest request, HttpServletResponse response) { userName = userName == null ? null : userName.toUpperCase(); ReportUtils.checkParameters(userName, reportName); if (printService.overload(userName, profile, reportName, whereCondition, otherParameters)) { throw new ReportException("数据量过大,无法提供服务"); } String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName); Map result = new HashMap<>(); // 相对路径,返回给前端 String pdfPath = ReportConstants.GENERATED_FILES_PATH + reportName + "/" + fileService.generateFileName(userName, profile, reportName, whereCondition, otherParameters, ReportConstants.PDF_FILE_TYPE) + "." + ReportConstants.PDF_FILE_TYPE; final File file = new File(ReportConstants.GENERATED_FILES_DIR + pdfPath); if (pageIndex == null || pageIndex == 1) { // 指定flush为true(强制刷新pdf) // 文件无效(不存在或过期),重新创建pdf文件 if ((flush != null && flush.booleanValue()) || !fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))) { // 参数pageIndex为null或1,表示是直接打印或预览第一页, // 需要生成第一页(可能页数过多,提示用户不支持预览打印),再在后台开线程生成总的pdf // 先生成第一页pdf Integer pageSize = printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters, file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE, "_1." + ReportConstants.PDF_FILE_TYPE), 1); result.put("pageSize", pageSize); // 再开线程生成后面页的pdf、总的pdf(即未分页的pdf) final String userNameCopy = userName; new Thread(new Runnable() { @Override public void run() { // 生成总的pdf printService.createPdfFile(userNameCopy, profile, reportName, whereCondition, otherParameters, file.getPath(), null); fileService.createPagedPdfFiles(file.getPath()); } }).start(); } else { result.put("pageSize", fileService.getPageSize(file.getPath())); } } else { // 文件无效(不存在或过期),重新创建pdf文件 if (!fileService.isFileValid( file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE, "_" + pageIndex + "." + ReportConstants.PDF_FILE_TYPE), fileService.getJrxmlFilePath(masterOfJrxml, reportName))) { printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters, file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE, "_" + pageIndex + "." + ReportConstants.PDF_FILE_TYPE), pageIndex); } } result.put("pdfPath", pdfPath); return result; } /** * 获取pdf数据(该接口暂时供手机端访问) * * @param userName * 不为null;当前账套名称 * @param profile * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev * @param reportName * 不为null;需要预览的报表的名称,不带任何后缀(如预览采购单,即为"Purchase") * @param whereCondition * 可为null;where之后的条件(包括where) * @param otherParameters * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数; * JSON格式,数据为键值对 * @param request * @param response * @return 包括pageSize、data(或overload) */ @RequestMapping(value = "/pdfData") @ResponseBody public Map getPdfData(String userName, String profile, String reportName, String whereCondition, String otherParameters, HttpServletRequest request, HttpServletResponse response) { userName = userName == null ? null : userName.toUpperCase(); ReportUtils.checkParameters(userName, reportName); Map result = new HashMap<>(); // 判断是否过载 if (printService.overload(userName, profile, reportName, whereCondition, otherParameters)) { result.put("data", ""); result.put("pageSize", 0); result.put("overload", true); } else { result = printService.preview(userName, profile, reportName, whereCondition, otherParameters, null); result.put("overload", false); } return result; } /** * 获取生成的pdf或者xls的信息 * * @param userName * 不为null;当前账套名称 * @param profile * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev * @param reportName * 不为null;需要预览的报表的名称,不带任何后缀(如预览采购单,即为"Purchase") * @param whereCondition * 可为null;where之后的条件(包括where) * @param otherParameters * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数; * JSON格式,数据为键值对 * @param fileType * 文件格式,pdf、xls、xls_with_only_data * @param request * @return 文件的信息 */ @RequestMapping(value = "/getGeneratedPdfOrXlsInformation") @ResponseBody public Map getGeneratedPdfOrXlsInformation(String userName, String profile, String reportName, String whereCondition, String otherParameters, String fileType, HttpServletRequest request) { userName = userName == null ? null : userName.toUpperCase(); ReportUtils.checkParameters(userName, reportName); Map result = new HashMap<>(); if (StringUtils.isEmpty(fileType)) { fileType = ReportConstants.PDF_FILE_TYPE; } String filePath = ReportConstants.GENERATED_FILES_PATH + reportName + "/" + fileService .generateFileName(userName, profile, reportName, whereCondition, otherParameters, fileType); File file = null; String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName); if (fileType.equals(ReportConstants.PDF_FILE_TYPE)) { file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.PDF_FILE_TYPE); result.put("valid", fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))); result.put("size", file.length()); } else if (fileType.equals(ReportConstants.EXCEL_FILE_TYPE)) { file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.EXCEL_FILE_TYPE); result.put("valid", fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))); result.put("size", file.length()); } else if (fileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) { file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.EXCEL_FILE_TYPE); result.put("valid", fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))); result.put("size", file.length()); } else { throw new ReportException("fileType只能为pdf、xls、xls_with_only_data"); } result.put("file", file.getPath()); return result; } }