Primefaces Extensions Document Viewer后端异常前端处理咨询
问题:PrimeFaces Extensions DocumentViewer 异常处理优化方案
场景说明
我使用PrimeFaces Extensions 12的documentViewer组件,前端代码如下:
<pe:documentViewer zoom="page-fit" pagemode="thumbs" id="iframeViewPdf" width="80%" height="800" url="/pdfServlet?id=#{param.id}"/>
后端通过Spring MVC控制器输出PDF字节流,代码如下:
@RequestMapping(value = "/pdfServlet") public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception { InputStream inputStream = null; OutputStream outputStream = null; try{ String documentId = request.getParameter("id"); inputStream = myRepository.getFileAsInputStream(documentId); outputStream = response.getOutputStream(); IOUtils.copy(inputStream, outputStream); }catch(Exception e){ // 以下操作均无效 // request.getRequestDispatcher(request.getContextPath() + "/error").forward(request, response); // response.sendRedirect(request.getContextPath() + "/error"); // throw e; // 如何实现跳转到错误页或在页面显示错误提示? }finally{ IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } }
当前问题
正常场景下代码运行正常,但后端发生异常时,前端无法正确处理:
- 直接抛出异常无效果
- 尝试重定向/转发到错误页时,始终提示"无法在响应提交后转发/重定向"
- 应用已配置全局异常跳转,但对该场景无效
更新信息
后端加载异常时,Viewer会显示错误响应(截图如下),想知道能否通过JavaScript处理这种情况:
优化方案
方案1:后端提前校验,避免响应提交后处理异常
在写入输出流前完成所有校验逻辑,确保不会在流操作后抛出异常,同时规范响应头设置:
@RequestMapping(value = "/pdfServlet") public void doGet(HttpServletRequest request, HttpServletResponse response) throws Exception { InputStream inputStream = null; OutputStream outputStream = null; try { String documentId = request.getParameter("id"); // 提前校验文档存在性、权限等 if (documentId == null || !myRepository.exists(documentId)) { response.sendError(HttpServletResponse.SC_NOT_FOUND, "文档不存在"); return; } // 设置正确的响应头,确保浏览器正确解析内容 response.setContentType("application/pdf"); response.setHeader("Content-Disposition", "inline; filename=\"document.pdf\""); inputStream = myRepository.getFileAsInputStream(documentId); outputStream = response.getOutputStream(); IOUtils.copy(inputStream, outputStream); outputStream.flush(); } catch (Exception e) { // 仅在响应未提交时处理异常 if (!response.isCommitted()) { response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "加载文档失败"); } } finally { IOUtils.closeQuietly(inputStream); IOUtils.closeQuietly(outputStream); } }
核心要点:
- 前置校验避免流操作后报错
- 设置规范的响应头,防止异常时浏览器解析混乱
- 仅在响应未提交时发送错误状态码
方案2:前端通过JS监听DocumentViewer加载状态
documentViewer本质是iframe,可通过监听其加载事件判断响应是否正常,结合AJAX提前校验文档可用性:
<pe:documentViewer zoom="page-fit" pagemode="thumbs" id="iframeViewPdf" width="80%" height="800" url="/pdfServlet?id=#{param.id}"/> <script> $(function() { const iframe = document.getElementById('iframeViewPdf'); iframe.addEventListener('load', function() { try { // 校验iframe内容类型是否为PDF const contentType = iframe.contentDocument.contentType; if (contentType !== 'application/pdf') { showError('文档加载失败,请检查文档状态'); } } catch (e) { // 跨域场景下无法访问iframe内容,通过AJAX提前校验 checkDocumentStatus(#{param.id}); } }); }); function checkDocumentStatus(docId) { $.ajax({ url: '/checkDocument', data: {id: docId}, success: function(res) { if (!res.success) { showError(res.message || '文档加载失败'); } }, error: function() { showError('网络异常,无法加载文档'); } }); } function showError(msg) { $('#errorContainer').text(msg).show(); $('#iframeViewPdf').hide(); } </script> <!-- 错误提示容器 --> <div id="errorContainer" style="display:none; color:#dc3545; font-size:18px; padding:20px;"></div>
核心要点:
- 监听iframe的load事件判断内容有效性
- 跨域场景下用AJAX前置校验文档状态
- 显示错误提示并隐藏异常的Viewer组件
方案3:全局异常处理器配合自定义错误响应
配置Spring MVC全局异常处理器,针对PDF请求返回纯文本错误而非跳转页面:
@ControllerAdvice public class GlobalExceptionHandler { @ExceptionHandler(Exception.class) public void handlePdfException(HttpServletRequest request, HttpServletResponse response, Exception e) throws IOException { if (!response.isCommitted()) { String requestUri = request.getRequestURI(); // 判断是否为PDF加载请求 if (requestUri.contains("/pdfServlet")) { response.setContentType("text/plain"); response.setStatus(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); response.getWriter().write("文档加载失败:" + e.getMessage()); } else { // 其他请求跳转到全局错误页 response.sendRedirect(request.getContextPath() + "/error"); } } } }
核心要点:
- 用
@ControllerAdvice统一处理异常 - 针对PDF请求返回纯文本错误,避免跳转导致的响应提交异常
- 仅处理未提交的响应
内容的提问来源于stack exchange,提问作者Mahmoud Saleh
相关产品推荐
相关产品推荐

