PrintController.java 17 KB

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