PrintController.java 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324
  1. package com.uas.report.controller;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.IOException;
  5. import java.io.OutputStream;
  6. import java.net.URLEncoder;
  7. import java.util.HashMap;
  8. import java.util.Map;
  9. import javax.servlet.ServletException;
  10. import javax.servlet.http.HttpServletRequest;
  11. import javax.servlet.http.HttpServletResponse;
  12. import org.apache.commons.lang.ArrayUtils;
  13. import org.slf4j.Logger;
  14. import org.slf4j.LoggerFactory;
  15. import org.springframework.beans.factory.annotation.Autowired;
  16. import org.springframework.stereotype.Controller;
  17. import org.springframework.util.StringUtils;
  18. import org.springframework.web.bind.annotation.RequestMapping;
  19. import org.springframework.web.bind.annotation.ResponseBody;
  20. import com.uas.report.core.exception.ReportException;
  21. import com.uas.report.service.FileService;
  22. import com.uas.report.service.PrintService;
  23. import com.uas.report.util.FileUtils;
  24. import com.uas.report.util.ReportConstants;
  25. import com.uas.report.util.ReportUtils;
  26. /**
  27. * 报表打印
  28. *
  29. * @author sunyj
  30. * @since 2016年8月16日 下午3:49:02
  31. */
  32. @Controller
  33. @RequestMapping("/print")
  34. public class PrintController {
  35. private static Logger logger = LoggerFactory.getLogger(PrintController.class);
  36. @Autowired
  37. private PrintService printService;
  38. @Autowired
  39. private FileService fileService;
  40. /**
  41. * 为UAS系统打印提供服务, 根据printType进行预览、打印、下载pdf、下载纯数据excel等操作
  42. *
  43. * @param userName
  44. * 不为null;当前账套名称
  45. * @param profile
  46. * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev
  47. * @param reportName
  48. * 不为null;需要导出的报表的名称,不带任何后缀(如导出采购单,即为"Purchase")
  49. * @param whereCondition
  50. * 可为null;where之后的条件(包括where)
  51. * @param otherParameters
  52. * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数;
  53. * JSON格式,数据为键值对
  54. * @param printType
  55. * 打印类型,可为PREVIEW_PRINT_TYPE、PRINT_PRINT_TYPE、PDF_PRINT_TYPE、
  56. * EXCEL_PRINT_TYPE
  57. * @param request
  58. * @param response
  59. */
  60. @RequestMapping()
  61. public void print(String userName, String profile, String reportName, String whereCondition, String otherParameters,
  62. String printType, HttpServletRequest request, HttpServletResponse response) {
  63. // printType为空,默认进入预览页
  64. if (StringUtils.isEmpty(printType)) {
  65. printType = ReportConstants.PREVIEW_PRINT_TYPE;
  66. }
  67. // 预览或打印
  68. if (printType.equals(ReportConstants.PREVIEW_PRINT_TYPE)
  69. || printType.equals(ReportConstants.PRINT_PRINT_TYPE)) {
  70. try {
  71. request.getRequestDispatcher("preview").forward(request, response);
  72. } catch (IOException | ServletException e) {
  73. throw new ReportException(e).setDetailedMessage(e);
  74. }
  75. }
  76. // 下载pdf、纯数据excel
  77. else if (printType.equals(ReportConstants.PDF_PRINT_TYPE)) {
  78. export(userName, profile, reportName, whereCondition, otherParameters, ReportConstants.PDF_FILE_TYPE, true,
  79. request, response);
  80. }
  81. // 该下载接口供UAS系统使用,应其要求,EXCEL_PRINT_TYPE只能为EXCEL(该值意思本应为下载全部数据的excel),
  82. // 导致与EXCEL_WITH_ONLY_DATA_FILE_TYPE(下载纯数据的excel)命名不相匹配
  83. else if (printType.equals(ReportConstants.EXCEL_PRINT_TYPE)) {
  84. export(userName, profile, reportName, whereCondition, otherParameters,
  85. ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE, true, request, response);
  86. } else {
  87. throw new ReportException("printType不合法");
  88. }
  89. }
  90. /**
  91. * 导出报表
  92. *
  93. * @param userName
  94. * 不为null;当前账套名称
  95. * @param profile
  96. * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev
  97. * @param reportName
  98. * 不为null;需要导出的报表的名称,不带任何后缀(如导出采购单,即为"Purchase")
  99. * @param whereCondition
  100. * 可为null;where之后的条件(包括where)
  101. * @param otherParameters
  102. * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数;
  103. * JSON格式,数据为键值对
  104. * @param exportFileType
  105. * 报表导出的格式,默认为pdf
  106. * @param flush
  107. * 是否强制刷新pdf、xls
  108. * @param request
  109. * @param response
  110. */
  111. @RequestMapping("/export")
  112. @ResponseBody
  113. public void export(String userName, String profile, String reportName, String whereCondition,
  114. String otherParameters, String exportFileType, Boolean flush, HttpServletRequest request,
  115. HttpServletResponse response) {
  116. ReportUtils.checkParameters(userName, reportName);
  117. String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName);
  118. if (StringUtils.isEmpty(exportFileType)) {
  119. exportFileType = ReportConstants.PDF_FILE_TYPE;
  120. }
  121. byte[] data = null;
  122. String filePath = ReportConstants.GENERATED_FILES_PATH + reportName + "/" + fileService
  123. .generateFileName(userName, profile, reportName, whereCondition, otherParameters, exportFileType);
  124. if (exportFileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) {
  125. filePath += "." + ReportConstants.EXCEL_FILE_TYPE;
  126. } else {
  127. filePath += "." + exportFileType;
  128. }
  129. File file = new File(ReportConstants.GENERATED_FILES_DIR + filePath);
  130. // 指定flush为true(强制刷新pdf、xls)
  131. // 文件无效(不存在或过期),创建
  132. if ((flush != null && flush.booleanValue())
  133. || !fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName))) {
  134. data = printService.export(userName, profile, reportName, whereCondition, otherParameters, exportFileType);
  135. if (ArrayUtils.isEmpty(data)) {
  136. throw new ReportException("报表导出失败:" + userName + "/" + reportName + "\n");
  137. }
  138. FileUtils.create(file.getPath(), data);
  139. } else {
  140. FileInputStream fileInputStream = null;
  141. try {
  142. fileInputStream = new FileInputStream(file);
  143. data = new byte[fileInputStream.available()];
  144. fileInputStream.read(data);
  145. } catch (IOException e) {
  146. throw new ReportException(e).setDetailedMessage(e);
  147. } finally {
  148. if (fileInputStream != null) {
  149. try {
  150. fileInputStream.close();
  151. } catch (IOException e) {
  152. throw new ReportException(e).setDetailedMessage(e);
  153. }
  154. }
  155. }
  156. }
  157. try {
  158. String exportFileName = reportName;
  159. if (exportFileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) {
  160. exportFileName += "." + ReportConstants.EXCEL_FILE_TYPE;
  161. } else {
  162. exportFileName += "." + exportFileType;
  163. }
  164. response.setHeader("Content-Disposition",
  165. "attachment;filename=" + URLEncoder.encode(exportFileName, "UTF-8"));
  166. OutputStream outputStream = response.getOutputStream();
  167. outputStream.write(data);
  168. outputStream.flush();
  169. outputStream.close();
  170. } catch (IOException e) {
  171. logger.error("浏览器重复请求!");
  172. }
  173. }
  174. /**
  175. * 报表预览时获取pdf流
  176. *
  177. * @param userName
  178. * 不为null;当前账套名称
  179. * @param profile
  180. * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev
  181. * @param reportName
  182. * 不为null;需要预览的报表的名称,不带任何后缀(如预览采购单,即为"Purchase")
  183. * @param whereCondition
  184. * 可为null;where之后的条件(包括where)
  185. * @param otherParameters
  186. * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数;
  187. * JSON格式,数据为键值对
  188. * @param pageIndex
  189. * 分页展示,当前页码,从0开始
  190. * @param flush
  191. * 是否强制刷新pdf、xls
  192. * @param request
  193. * @param response
  194. * @return 包括pageSize、pdfPath
  195. */
  196. @RequestMapping(value = "/loadPdfData")
  197. @ResponseBody
  198. public Map<String, Object> loadPdfData(final String userName, final String profile, final String reportName,
  199. final String whereCondition, final String otherParameters, Integer pageIndex, Boolean flush,
  200. HttpServletRequest request, HttpServletResponse response) {
  201. ReportUtils.checkParameters(userName, reportName);
  202. String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName);
  203. Map<String, Object> result = new HashMap<>();
  204. // 相对路径,返回给前端
  205. String pdfPath = ReportConstants.GENERATED_FILES_PATH + reportName + "/"
  206. + fileService.generateFileName(userName, profile, reportName, whereCondition, otherParameters,
  207. ReportConstants.PDF_FILE_TYPE)
  208. + "." + ReportConstants.PDF_FILE_TYPE;
  209. final File file = new File(ReportConstants.GENERATED_FILES_DIR + pdfPath);
  210. if (pageIndex == null || pageIndex == 1) {
  211. // 指定flush为true(强制刷新pdf)
  212. // 文件无效(不存在或过期),重新创建pdf文件
  213. if ((flush != null && flush.booleanValue()) || !fileService.isFileValid(file.getPath(),
  214. fileService.getJrxmlFilePath(masterOfJrxml, reportName))) {
  215. // 参数pageIndex为null或1,表示是直接打印或预览第一页,
  216. // 需要生成第一页(可能页数过多,提示用户不支持预览打印),再在后台开线程生成总的pdf
  217. // 先生成第一页pdf
  218. Integer pageSize = printService.createPdfFile(userName, profile, reportName, whereCondition,
  219. otherParameters, file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE,
  220. "_1." + ReportConstants.PDF_FILE_TYPE),
  221. 1);
  222. result.put("pageSize", pageSize);
  223. // 再开线程生成后面页的pdf、总的pdf(即未分页的pdf)
  224. new Thread(new Runnable() {
  225. @Override
  226. public void run() {
  227. // 生成总的pdf
  228. printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters,
  229. file.getPath(), null);
  230. fileService.createPagedPdfFiles(file.getPath());
  231. }
  232. }).start();
  233. } else {
  234. result.put("pageSize", fileService.getPageSize(file.getPath()));
  235. }
  236. } else {
  237. // 文件无效(不存在或过期),重新创建pdf文件
  238. if (!fileService.isFileValid(
  239. file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE,
  240. "_" + pageIndex + "." + ReportConstants.PDF_FILE_TYPE),
  241. fileService.getJrxmlFilePath(masterOfJrxml, reportName))) {
  242. printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters,
  243. file.getPath().replace("." + ReportConstants.PDF_FILE_TYPE,
  244. "_" + pageIndex + "." + ReportConstants.PDF_FILE_TYPE),
  245. pageIndex);
  246. }
  247. }
  248. result.put("pdfPath", pdfPath);
  249. return result;
  250. }
  251. /**
  252. * 获取生成的pdf或者xls的信息
  253. *
  254. * @param userName
  255. * 不为null;当前账套名称
  256. * @param profile
  257. * 可选(UAS等系统不必传递该参数),用于标识请求源(B2C、B2B)是正式、测试还是开发版本:prod、test、dev
  258. * @param reportName
  259. * 不为null;需要预览的报表的名称,不带任何后缀(如预览采购单,即为"Purchase")
  260. * @param whereCondition
  261. * 可为null;where之后的条件(包括where)
  262. * @param otherParameters
  263. * 若模板已指定需要的参数,则不可为null;其他参数,区别于whereCondition,报表某些字段的值取决于这些参数;
  264. * JSON格式,数据为键值对
  265. * @param fileType
  266. * 文件格式,pdf、xls、xls_with_only_data
  267. * @param request
  268. * @return 文件的信息
  269. */
  270. @RequestMapping(value = "/getGeneratedPdfOrXlsInformation")
  271. @ResponseBody
  272. public Map<String, Object> getGeneratedPdfOrXlsInformation(String userName, String profile, String reportName,
  273. String whereCondition, String otherParameters, String fileType, HttpServletRequest request) {
  274. ReportUtils.checkParameters(userName, reportName);
  275. Map<String, Object> result = new HashMap<>();
  276. if (StringUtils.isEmpty(fileType)) {
  277. fileType = ReportConstants.PDF_FILE_TYPE;
  278. }
  279. String filePath = ReportConstants.GENERATED_FILES_PATH + reportName + "/" + fileService.generateFileName(
  280. userName, profile, reportName, whereCondition, otherParameters, ReportConstants.PDF_FILE_TYPE);
  281. File file = null;
  282. String masterOfJrxml = printService.getMasterOfJrxml(userName, reportName);
  283. if (fileType.equals(ReportConstants.PDF_FILE_TYPE)) {
  284. file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.PDF_FILE_TYPE);
  285. result.put("valid",
  286. fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName)));
  287. result.put("size", file.length());
  288. } else if (fileType.equals(ReportConstants.EXCEL_FILE_TYPE)) {
  289. file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.EXCEL_FILE_TYPE);
  290. result.put("valid",
  291. fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName)));
  292. result.put("size", file.length());
  293. } else if (fileType.equals(ReportConstants.EXCEL_WITH_ONLY_DATA_FILE_TYPE)) {
  294. file = new File(ReportConstants.GENERATED_FILES_DIR + filePath + "." + ReportConstants.EXCEL_FILE_TYPE);
  295. result.put("valid",
  296. fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(masterOfJrxml, reportName)));
  297. result.put("size", file.length());
  298. } else {
  299. throw new ReportException("fileType只能为pdf、xls、xls_with_only_data");
  300. }
  301. result.put("file", file.getPath());
  302. return result;
  303. }
  304. }