【问题标题】:Gracefully Handle REST Server Error优雅地处理 REST 服务器错误
【发布时间】:2015-05-15 02:59:43
【问题描述】:

我有一个动态生成 PDF 的应用程序(通过 service/generatePdf 访问)。

它返回一个带有 content-type="application/pdf" 的 HTTP 响应,并将 outputStream 设置为二进制内容。

根据业务规范,当用户单击按钮时,我们需要打开一个显示该 PDF 的新窗口/选项卡。

提交下面的表格,这一切都可以在 Happy Path 上完美运行,其中响应是实际的 PDF。

<form action="service/generatePdf" method="post" name="PdfForm" target="_blank">

但是,当 PDF 因任何原因无法生成时,效果不佳。例如,假设 HTTP 响应 outputStream 为空。

我想要能够做的是在第一页上显示一条漂亮的错误消息,而不是打开新窗口/标签。

但似乎没有任何方法可以做到这一点。您的选择似乎是

  • 返回一个有效的 PDF,或者
  • 浏览器的 PDF 插件如何处理损坏的文件

我尝试过 jQuery、Ajax、jQuery Form Plugin、jQuery Download plugin 插件,但似乎没有任何效果。

【问题讨论】:

  • 我很欣赏这种热情,但是当我说“我有一个应用程序”时,我的意思是我继承了一个 REST Java 应用程序,其(部分)URL 是“service/generatePdf”(实际的 URL 是无关)。我负责生成 PDF 的 REST 应用程序和使用它的 Javascript。
  • 如果它是真正的 REST 服务,那么您应该能够检查 HTTP 响应 Status Code 并确定操作是否成功。如果是,您可以在响应正文中获取 base64 字符串并将其作为新窗口打开。见stackoverflow.com/a/2805990/211627
  • 我已经看到了,我认为它接近我所需要的。不幸的是,我们需要支持 IE8,当 PDF 太大时,该解决方案会失败。但这个概念正是我所需要的。
  • 告诉“他们”,您可以立即为除 IE8 之外的所有浏览器解决此问题。那个浏览器比较复杂,解决方案会带你about 10 months。
  • 哈! :) 要是。相信我,IE8 是我存在的祸根,也是 P.O.S.死得不够快。

标签: javascript jquery rest pdf


【解决方案1】:

服务器应通过 HTTP 状态代码指示错误或成功(例如 200 = OK,500 = 错误)。您可以使用 JQuery 在您的 REST 客户端中捕获这一点

$.ajax({
    url: 'service/generatedPDF',
    error: function(jqXHR, textStatus, errorThrown) {
        ... // show error message
    },
).done(function(data) {
    // data contains the PDF
}

最好只在服务器上创建 PDF,将其放在临时存储中,然后在响应中发送该 PDF 的 URL。一旦客户端下载了文件,或者在某个下载之后,PDF 就会从商店中删除。

在这种情况下,您只需使用从服务器收到的 URL 打开一个新窗口。

如果服务器在初始请求中提供了 PDF,您可以将其转换为 Data URI 并在新窗口中打开该数据 URI。

【讨论】:

  • 据我所知,Ajax 不支持二进制数据。当我做了与你类似的事情时,返回的“数据”对象有一个看起来像二进制 PDF 内容的字符串,但我怀疑二进制数据字符串与 byte[] 数组完全相同。通过 Ajax 返回 URL 并进行单独检索的想法听起来是最干净的,但它需要对应用程序进行一些严重的返工
  • 这是一个将二进制响应转换为数据 URL 的示例。 stackoverflow.com/questions/20035615/…
  • 我想我会使用数据 URI 而不是临时存储数据并提供链接。这种方式存在很多复杂性(跟踪何时删除临时文件)。 LiveCycle 对 SOAP 调用的附件做了类似的事情,但这是有问题的(客户端会出错,因为文件在下载之前就被删除了)。恕我直言,使用数据 URI 方法消除了响应处理的异步方面,从长远来看,这将更简单且不易出错。
  • @RobMcDougall 我同意,只是数据 URI 的大小是有限的。
  • 我同意,只是数据 URI 的大小是有限的,这是一种交易杀手。一切都会正常工作,直到有一天某个 IE8 用户因为 PDF 太大而失败。
【解决方案2】:

这是一个相当普遍的要求。您需要让您的 REST 应用程序更智能一些。它需要检查 LiveCycle PDF 生成的结果,如果不成功,则返回 HTML 响应(内容类型为 text/html)。

浏览器相当愚蠢。它检查传入响应的内容类型,并根据内容类型启动插件。然后由插件来处理响应。 PDF插件也不是那么亮眼,它假设传入的数据流是PDF,如果是空的,就会报错。

这里的关键是将正确的内容类型(和内容)发送到浏览器,这意味着检查 PDF 结果并在 PDF 结果失败时发送更合适的响应。

我们也经常在 LiveCycle 编排中看到这一点。诱惑是将 PDF 生成为 com.adobe.idp.Document 对象,然后直接返回该对象。这会导致您描述的类似问题。相反,更好的方法是检查 PDF 生成的结果。 如果有效,则返回该响应。如果 PDF 生成失败,则在 com.adobe.idp.Document 对象(具有适当的 text/html 内容类型)中构造一个 HTML 响应,然后将其返回。

【讨论】:

  • 如上所述,Adobe LifeCycle 的事情是一个红鲱鱼,但没关系,我认为我们仍然在轨道上...... :) 我可以让 REST 层尽可能智能成为。所以你是说如果一切都很好发送“application-pdf”响应,但如果出现问题,发送一个“test/html”响应,对吗?如果是这样,我可以这样做。但这仍然意味着会为错误情况打开一个新窗口,它只会显示 HTML 而不是 PDF。我希望出现错误,不打开新窗口而是在原始页面上显示 HTML。
  • > 所以你是说如果一切正常就发送“application-pdf”响应,但是如果出现问题,就发送一个“test/html”响应,对吗?正确
  • > 我希望出现错误,不打开新窗口而是在原始页面上显示 HTML。 我认为这是一个 HTML 问题。 AFAIK,响应的位置取决于您的目标属性。你真的没有机会让它以回应为条件。我认为您唯一的选择是编写大量使用 XMLHTTPRequest 对象与服务器对话并控制响应的呈现的 javascript。
  • 我认为这是一个 HTML 问题。 AFAIK,响应的位置取决于您的目标属性。你真的没有机会让它以回应为条件。 ....这也是我要得出的结论。
  • 在新窗口中弹出 HTML 错误消息并不是世界上最糟糕的事情。我想我会向最终用户提出这个建议,看看它是否会飞。它可能并不理想,但也不是世界末日。
猜你喜欢
  • 2018-11-10
  • 2010-09-21
  • 2019-05-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多