向服务器POST XML,接收PDF文件。

3
类似于这个问题,我们正在开发一个Web应用程序,客户端单击按钮从服务器接收PDF。现在,我们使用jQuery的.ajax()方法向后端发送数据(我们发送XML)以生成PDF,并将其作为application/pdf在HTTP响应中返回。
对于那个问题的一个答案要求服务器端将PDF保存到磁盘,以便可以返回客户端获取的URL。但是我不希望后端缓存任何内容。
另一个答案建议使用jQuery插件,但是当您查看其代码时,它实际上生成了一个form元素,然后提交了form。该方法对我们无效,因为我们在HTTP请求的正文中发送XML数据。
有没有办法让浏览器打开PDF而不会在服务器端缓存PDF,也不需要我们放弃使用XML解决方案发送数据到服务器?
(我希望浏览器的行为类似于提交form元素时的行为-进行POST操作,然后浏览器查看Content-type头来确定下一步该执行什么操作,例如在浏览器窗口中加载PDF,就像Safari一样)
4个回答

1
这里有一个示例表单,允许您输入一些文本,然后浏览器中会出现一个PDF文件。对我而言是这样的。我所做的就是在内存中创建PDF,将响应正文设置为PDF,响应头设置为application/pdf。 就是这样。
请参阅http://129.33.194.254:8080/makepdf.rsp以获取工作示例。
如果对您不起作用,请使用wireshark跟踪http事务。
<html>
<body>
<%
    either none? text: select request/content 'data [
        %>
        <strong> PDF Test </strong>
        <form method="post">
        Enter some text:
        <input type="text" name="data" value="">
        <input type="submit" value="Submit">
        </form>
        <%
    ][
    if not exists? %pdf-maker.r [
        write %pdf-maker.r read http://www.colellachiara.com/soft/Misc/pdf-maker.r
    ]
    if not value? 'layout-pdf [
        *do %pdf-maker.r
    ]
    response/buffer: layout-pdf compose/deep [[textbox [(dehex text)]]]
    response/set-header 'Content-type "application/pdf"
    ]
%>
</body>
</html>

这是什么语言?我从未见过这样的代码。我也无法解析它是否通过HTTP请求正文发送数据(而不是作为URL编码查询字符串),并且它似乎以某种方式修改响应正文。 - Shaggy Frog
语言Rebol(参见http://www.rebol.com)并不重要。如果我使用GET而不是POST,它也可以正常工作。我不明白为什么您说只能使用GET进行解析。是的,在这个框架中,您必须创建一个响应以发送回客户端,并且我们只需设置响应/缓冲区,Web服务器就会将其流回客户端。我很确定这也是Zope和其他服务器的做法。如果使用Firefox,您可以使用http headers插件查看您的Web服务器使用自己的代码发送回来的内容,以进行关键调试。 - Graham Chiu
(1) 语言肯定很重要,因为我希望在客户端只使用HTML/JS,在服务器端使用Java。(2) 我使用“解析”一词的意思是“我正在尝试阅读它以了解它的作用”。(3) 我不能使用GET而不是POST,因为GET不允许任意数据体(有关此内容,请阅读HTTP规范)(4) 根据您的答案和评论,我认为您误解了问题和要求。 - Shaggy Frog
我给你的例子使用了HTTP POST方法(<form method="post">)。 - Graham Chiu

1

我看到了一些解决方案:

1)将其提交到一个简单的servlet,通过xslt处理器(例如saxon)流式传输文件,将其转换为xsl-fo(一种xml页面描述语言),然后使用FOP或RenderX将其转换为PDF。

2)将其提交到servlet,将xml解析为bean数组或其他适当结构化数据模型,可以由报告引擎处理,然后将其传递给报告引擎(例如Birt、JasperReports等),支持PDF呈现为标准输出格式。如果XML很小,您可能只需将其完全传递给报告引擎servlet,并在报告本身内部进行处理。我知道其中一个具有JavaScript数据源,可以进行转换。

3)在servlet中使用iText从解析的xml生成PDF,但我以前从未使用过,所以不知道它如何工作。


你完全误解了。我已经在创建PDF文件了。我不需要帮助。我需要的是在用户点击按钮后,将该PDF文件传送到他们的浏览器中。 - Shaggy Frog
抱歉。我猜你的问题与请求是由JavaScript处理而不是浏览器本身有关。如果您将调用更改为在新窗口或选项卡中打开并让浏览器处理它,只要在响应头中设置正确的contentType(以及正确的文件名扩展名),它就应该做正确的事情。 - Peter Tillemans
在新窗口中打开需要一个位置,这需要一个URL。这意味着PDF必须可用,并且在服务器端缓存,以进行第二个HTTP请求(GET)。正如我最初所述,我不想在服务器端缓存任何东西(写入磁盘)。 - Shaggy Frog
它确实需要一个GET的URL,但这并不意味着必须将文件写入磁盘。它只是意味着请求必须发送到能够编写PDF输出的进程。Cocoon flowscript具有可以执行此操作的continuations -- 您的脚本发送一个继续URL,该URL从脚本离开的地方继续执行。(我认为像node.js或twisted这样的框架也有类似的方法,但不确定。) - Steven D. Majewski
你说得对,这个文件不需要写入磁盘。然而,延续的概念用另一个问题(磁盘I/O管理)替换了它,因为你不是将PDF写入磁盘,而是保存一些可以创建该PDF的中间信息到一边。这些信息需要存储在某种数据结构中,多个生产者将向其添加内容,多个消费者将从其中删除内容。 - Shaggy Frog

0
我曾经遇到过完全相同的问题,唯一的区别是:我使用JSON将数据发送到服务器。我的解决方案是:
在您的页面上创建一个隐藏表单(#printform),其中包含一个输入字段(#printdata),并将参数作为字符串提交:
  $("#printdata").val(JSON.stringify(my_json_data_object));
  $("#printform").submit();

在我的 my_json_data_object 中,我存储了所有创建 PDF 所需的数据。在服务器上,我需要使用 JSON.parse(...) 将参数解析回 JSON 对象。通过这种解决方案,我可以创建并流式传输 PDF 文件到客户端,而无需将它们保存在服务器上。不要忘记在响应中设置以下标头:
content-type: application/json
content-disposition: attachment; filename="output.pdf"

0
只需创建适当的内容头并在响应中写回PDF即可。您不需要像不需要缓存动态生成的HTML或图像一样缓存所创建的PDF。

我正在做这件事。问题在于客户端浏览器没有处理HTTP响应。 - Shaggy Frog
我建议您使用Wireshark跟踪交易并查看您正在生成的标头。这应该可以告诉您为什么它对您不起作用。 - Graham Chiu
@ShaggyFrog:不要在客户端使用ajax方法,只需进行常规提交。如果您让浏览器自行处理,它会自行处理。 - Steven D. Majewski
请描述一下您所说的“只需进行常规POST”的意思,记住我正在尝试将XML作为HTTP请求正文的一部分发送。 - Shaggy Frog
那么,HTTP响应长什么样子? - Graham Chiu

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接