Browse Source

超过500页不支持预览打印,需先下载

sunyj 9 years ago
parent
commit
7ace98b416

+ 31 - 24
src/main/java/com/uas/report/controller/PrintController.java

@@ -197,39 +197,46 @@ public class PrintController {
 	 */
 	@RequestMapping(value = "/loadPdfData")
 	@ResponseBody
-	public Map<String, Object> loadPdfData(String userName, String profile, String reportName, String whereCondition,
-			String otherParameters, Integer pageIndex, HttpServletResponse response) {
+	public Map<String, Object> loadPdfData(final String userName, final String profile, final String reportName,
+			final String whereCondition, final String otherParameters, Integer pageIndex,
+			HttpServletResponse response) {
 		ReportUtils.checkParameters(userName, reportName);
 		logger.info("开始预览报表:" + reportName);
-		Map<String, Object> result = null;
+		Map<String, Object> result = new HashMap<>();
 
 		// 相对路径,返回给前端
 		String pdfPath = ReportConstants.GENERATED_FILES_PATH + reportName + "/"
 				+ fileService.generateFileName(userName, profile, reportName, whereCondition, otherParameters) + ".pdf";
-		File file = new File(PathUtils.getAppPath() + pdfPath);
-		// 文件无效(不存在或过期),重新创建pdf文件
-		if (!fileService.isFileValid(
-				pageIndex == null ? file.getPath() : file.getPath().replace(".pdf", "_" + pageIndex + ".pdf"),
-				fileService.getJrxmlFilePath(userName, reportName))) {
-			// 参数pageIndex为null或1,表示是直接打印或预览第一页(需要先生成总的pdf)
-			result = printService.preview(userName, profile, reportName, whereCondition, otherParameters, pageIndex);
-			byte[] data = null;
-			if (result != null && result.containsKey("data")) {
-				data = (byte[]) result.remove("data");
-			}
-			if (ArrayUtils.isEmpty(data)) {
-				throw new ReportException("获取预览数据失败");
-			}
-			if (pageIndex == null || pageIndex == 1) {
-				FileUtils.create(file.getPath(), data);
-				// 同时生成分页的pdf
-				fileService.createPagedPdfFiles(file.getPath());
+		final File file = new File(PathUtils.getAppPath() + pdfPath);
+		if (pageIndex == null || pageIndex == 1) {
+			// 文件无效(不存在或过期),重新创建pdf文件
+			if (!fileService.isFileValid(file.getPath(), fileService.getJrxmlFilePath(userName, reportName))) {
+				// 参数pageIndex为null或1,表示是直接打印或预览第一页,
+				// 需要生成第一页(可能页数过多,提示用户不支持预览打印),再后台开线程生成总的pdf
+				// 先生成第一页pdf
+				Integer pageSize = printService.createPdfFile(userName, profile, reportName, whereCondition,
+						otherParameters, file.getPath().replace(".pdf", "_1.pdf"), 1);
+				result.put("pageSize", pageSize);
+				// 再开线程生成后面页的pdf、总的pdf(即未分页的pdf)、纯数据excel
+				new Thread(new Runnable() {
+					@Override
+					public void run() {
+						// 生成总的pdf
+						printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters,
+								file.getPath(), null);
+						fileService.createPagedPdfFiles(file.getPath());
+					}
+				}).start();
 			} else {
-				FileUtils.create(file.getPath().replace(".pdf", "_" + pageIndex + ".pdf"), data);
+				result.put("pageSize", fileService.getPageSize(file.getPath()));
 			}
 		} else {
-			result = new HashMap<>();
-			result.put("pageSize", fileService.getPageSize(file.getPath()));
+			// 文件无效(不存在或过期),重新创建pdf文件
+			if (!fileService.isFileValid(file.getPath().replace(".pdf", "_" + pageIndex + ".pdf"),
+					fileService.getJrxmlFilePath(userName, reportName))) {
+				printService.createPdfFile(userName, profile, reportName, whereCondition, otherParameters,
+						file.getPath().replace(".pdf", "_" + pageIndex + ".pdf"), pageIndex);
+			}
 		}
 		result.put("pdfPath", pdfPath);
 		logger.info("预览报表成功:" + reportName);

+ 23 - 0
src/main/java/com/uas/report/service/PrintService.java

@@ -52,4 +52,27 @@ public interface PrintService {
 	public Map<String, Object> preview(String userName, String profile, String reportName, String whereCondition,
 			String otherParameters, Integer pageIndex);
 
+	/**
+	 * 获取第pageIndex页的pdf数据并写入pdfFilePath路径下
+	 * 
+	 * @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 pdfFilePath
+	 *            该报表对应的pdf绝对路径
+	 * @param pageIndex
+	 *            页码
+	 * @return 总页数
+	 */
+	public Integer createPdfFile(String userName, String profile, String reportName, String whereCondition,
+			String otherParameters, String pdfFilePath, Integer pageIndex);
+
 }

+ 20 - 0
src/main/java/com/uas/report/service/impl/PrintServiceImpl.java

@@ -11,6 +11,7 @@ import java.util.Map;
 
 import javax.sql.DataSource;
 
+import org.apache.commons.lang.ArrayUtils;
 import org.apache.log4j.Logger;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -22,6 +23,7 @@ import com.uas.report.core.exception.ReportException;
 import com.uas.report.service.FileService;
 import com.uas.report.service.PrintService;
 import com.uas.report.util.DataSourceUtils;
+import com.uas.report.util.FileUtils;
 import com.uas.report.util.ReportConstants;
 
 import net.sf.jasperreports.engine.JRException;
@@ -314,4 +316,22 @@ public class PrintServiceImpl implements PrintService {
 		// }
 	}
 
+	@Override
+	public Integer createPdfFile(String userName, String profile, String reportName, String whereCondition,
+			String otherParameters, String pdfFilePath, Integer pageIndex) {
+		File file = new File(pdfFilePath);
+		Map<String, Object> result = preview(userName, profile, reportName, whereCondition, otherParameters, pageIndex);
+		byte[] data = null;
+		Integer pageSize = null;
+		if (result != null && result.containsKey("data") && result.containsKey("pageSize")) {
+			data = (byte[]) result.remove("data");
+			pageSize = (Integer) result.remove("pageSize");
+		}
+		if (ArrayUtils.isEmpty(data) || pageSize == null) {
+			throw new ReportException("获取预览数据失败");
+		}
+		FileUtils.create(file.getPath(), data);
+		return pageSize;
+	}
+
 }

+ 114 - 45
src/main/webapp/resources/js/preview2/app.js

@@ -10,6 +10,8 @@ var spinner;
 
 // 能打印的最大页数(页数超过,需要先下载pdf,再打印)
 var PRINT_MAX_PAGE_SIZE = 500;
+var ALERT_FILE_TOO_LARGE = "pdf超过" + PRINT_MAX_PAGE_SIZE
+		+ "页,建议先下载到本地,再进行查看或打印";
 var pdfDoc;
 // 页码
 var pageIndex;
@@ -21,23 +23,18 @@ var scale;
 var winHeight;
 // 浏览器窗口宽度
 var winWidth;
-// hiddenFrame是否加载成功
-var hiddenFrameLoaded = false;
 // 将要打印的总的pdf(整个文档,而不是某一页的pdf)相对路径
 var wholePdfPath;
 // 某一页pdf文件的路径
 var pagedPdfPath;
 // 参数打印类型,可能为PRINT、PREVIEW
 var printType = getParameter("printType");
+// 首次加载页面()
+var firstRequest = true;
 
 getWindowWidth();
 loadData(1);
 
-// 是否立即打印
-if (printType == 'PRINT') {
-	printPdf();
-}
-
 // 缩小,最小不小于原大小的0.2/1.2倍
 $("#zoomOut").click(function() {
 	if (scale >= 0.2) {
@@ -82,6 +79,11 @@ $("#pageIndex").keypress(function(event) {
 			if (value == pageIndex) {
 				return;
 			}
+			if (pageSize > PRINT_MAX_PAGE_SIZE) {
+				alert(ALERT_FILE_TOO_LARGE);
+				return;
+			}
+			firstRequest = false;
 			pageIndex = value;
 			loadData(pageIndex);
 		} else {
@@ -99,12 +101,28 @@ $("#print").click(function() {
 });
 
 // 下载pdf
-$("#downloadPdf").click(function() {
-	if (!pdfDoc) {
-		return;
-	}
+$("#downloadPdf").click(
+		function() {
+			if (!pdfDoc) {
+				return;
+			}
+			console.log(new Date().format()
+					+ " ---- subscribed wholePdfGeneratedSignal");
+			$.subscribe("wholePdfGeneratedSignal", downloadPdf);
+			waitWholePdfGenerated();
+		});
+
+/**
+ * 下载文件
+ */
+function downloadPdf() {
+	hideLoading();
+	console.log(new Date().format()
+			+ " ---- received and unsubscribe wholePdfGeneratedSignal");
+	$.unsubscribe("wholePdfGeneratedSignal", downloadPdf);
+	console.log(new Date().format() + " ---- start download...");
 	window.location = downloadUrl("pdf");
-});
+}
 
 // 下载纯数据excel
 $("#downloadExcelWithOnlyData").click(function() {
@@ -153,8 +171,9 @@ function getWindowWidth() {
  * 打印
  */
 function printPdf() {
+	hideLoading();
 	if (pageSize > PRINT_MAX_PAGE_SIZE) {
-		alert("文件过大,建议先下载到本地,再进行打印");
+		alert(ALERT_FILE_TOO_LARGE);
 		return;
 	}
 	console.log(new Date().format() + " ---- start print...");
@@ -171,23 +190,34 @@ function printPdf() {
  */
 function loadPagedPdf(pagedPdfPath, ifPreloadWholePdf) {
 	// var dfd = $.Deferred();
-	PDFJS.getDocument(pagedPdfPath).then(
-			function(pdfDoc_) {
-				// 更新页码
-				document.getElementById('pageIndex').value = pageIndex;
-				pdfDoc = pdfDoc_;
-				// 第一页文档渲染完成后,再加载整个文档
-				if (ifPreloadWholePdf) {
-					console.log(new Date().format()
-							+ " ---- subscribed renderTaskFinishedSignal");
-					$.subscribe("renderTaskFinishedSignal", loadWholePdf);
-				}
-				// Initial/first page rendering
-				renderPage();
-				// $.when(rend("getDocument promised");
-				// dfd.resolve();
-				// });
-			});
+	PDFJS
+			.getDocument(pagedPdfPath)
+			.then(
+					function(pdfDoc_) {
+						// 更新页码
+						document.getElementById('pageIndex').value = pageIndex;
+						pdfDoc = pdfDoc_;
+						// 第一页文档渲染完成后,再加载整个文档
+						if (ifPreloadWholePdf) {
+							if (printType == 'PRINT'
+									&& pageSize > PRINT_MAX_PAGE_SIZE) {
+								alert(ALERT_FILE_TOO_LARGE);
+								hideLoading();
+							} else {
+								console
+										.log(new Date().format()
+												+ " ---- subscribed wholePdfGeneratedSignal");
+								$.subscribe("wholePdfGeneratedSignal",
+										loadWholePdf);
+								waitWholePdfGenerated();
+							}
+						}
+						// Initial/first page rendering
+						renderPage();
+						// $.when(rend("getDocument promised");
+						// dfd.resolve();
+						// });
+					});
 	// return dfd.promise;
 }
 
@@ -210,12 +240,13 @@ function loadData(page) {
 			// 第pageIndex页的pdf文件路径
 			pagedPdfPath = wholePdfPath.replace(".pdf", "_" + pageIndex
 					+ ".pdf");
-			if (pageIndex == 1) {
+			if (firstRequest) {
 				pageSize = data.pageSize;
 				document.getElementById('pageSize').textContent = pageSize;
 				document.title = getParameter("reportName");
 				// 加载第一页文档,并且预加载整个文档
 				loadPagedPdf(pagedPdfPath, true);
+				showLoading();
 				// $.when(getDocument()).done(loadWholePdf);
 				// console.log(renderTask._internalRenderTask.running);
 			} else {
@@ -247,29 +278,62 @@ function loadData(page) {
  */
 function loadWholePdf() {
 	console.log(new Date().format()
-			+ " ---- received and unsubscribe renderTaskFinishedSignal");
-	$.unsubscribe("renderTaskFinishedSignal", loadWholePdf);
-	// 之前已经加载,不再加载
-	if (hiddenFrameLoaded) {
-		return;
-	}
-	// 渲染完成后延迟一小段时间预加载整个文档
-	sleep(500);
-	if (pageSize > PRINT_MAX_PAGE_SIZE) {
-		console.log(new Date().format() + " ---- 文件过大,建议先下载到本地,再进行打印");
-		hiddenFrameLoaded = true;
-		return;
-	}
+			+ " ---- received and unsubscribe wholePdfGeneratedSignal");
+	$.unsubscribe("wholePdfGeneratedSignal", loadWholePdf);
 	// 开始加载
 	console.log(new Date().format() + " ---- hiddenFrame loading...");
 	hiddenFrame.src = wholePdfPath;
+	setTimeout("printPdf()", 1000);
+}
+
+/**
+ * 每隔一定时间查询文件状态,直到文件有效
+ */
+function waitWholePdfGenerated() {
+	showLoading();
+	var valid = getGeneratedPdfOrXlsInformation("pdf").valid;
+	if (!valid) {
+		console.log(new Date().format() + " ---- 文件还未生成");
+		console.log(new Date().format() + " ---- wait 1000ms")
+		setTimeout("waitWholePdfGenerated()", 1000);
+	} else {
+		console.log(new Date().format() + " ---- 文件已生成");
+		console.log(new Date().format()
+				+ " ---- published wholePdfGeneratedSignal");
+		$.publish("wholePdfGeneratedSignal", waitWholePdfGenerated);
+	}
+}
+
+/**
+ * 获取生成的pdf或者xls的信息
+ * 
+ * @param pdfOrXls
+ *            pdf或者xls
+ */
+function getGeneratedPdfOrXlsInformation(pdfOrXls) {
+	var data;
+	$.ajax({
+		type : "get",
+		async : false,
+		url : "print/getGeneratedPdfOrXlsInformation" + window.location.search
+				+ "&pdfOrXls=" + pdfOrXls,
+		success : function(result) {
+			console
+					.log(new Date().format() + " ---- "
+							+ JSON.stringify(result));
+			data = result;
+		}
+	});
+	return data;
 }
 
 /**
  * Get page info from document, resize canvas accordingly, and render page
  */
 function renderPage() {
-	hideLoading();
+	if (!firstRequest) {
+		hideLoading();
+	}
 	if (!pdfDoc) {
 		return;
 	}
@@ -351,6 +415,11 @@ function nextPage() {
 	if (!pdfDoc || pageIndex >= pageSize) {
 		return;
 	}
+	if (pageSize > PRINT_MAX_PAGE_SIZE) {
+		alert(ALERT_FILE_TOO_LARGE);
+		return;
+	}
+	firstRequest = false;
 	pageIndex++;
 	loadData(pageIndex);
 }