c# 如何动态生成 pdf 文件并将其流式传输到浏览器,而无需写入本地目录

c# How to generate and stream a pdf file to browser on the fly without ever having to write to a local directory

我正在编写一个简单的 asp.net,用户可以将对象列表下载为 PDF 文档。单击按钮 "get pdf" 时,客户端浏览器应询问用户他们希望将文件保存在何处。就是这样。非常简单。

我找到了几个解释如何从数据表生成 PDF 的指南,但所有这些似乎都要求您将 pdf 保存到某种临时文件,并在此过程中将其存储在本地。

PdfWriter writer = PdfWriter.GetInstance(document, new FileStream("c://sample.pdf", FileMode.Create));

真的有必要将文件保存在本地然后传递给用户,用户可以选择再次保存文件吗?我在这里想念什么吗?有没有办法在文件上生成PDF,然后将其传递给客户端浏览器?

编辑:

具体来说,我在这里说的可能是直接将流发送到客户端浏览器,文件完全是动态生成的。在用户收到 "do you want to download this file" 提示之前没有本地存储。

这个问题令人困惑,因为您不清楚 "locally" 的意思。

通常当您在服务器上创建 PDF ("remotely") 时,您不需要将 PDF 存储在服务器的文件系统上。您只需在内存中创建 PDF 并将字节传递给 Response.OutputStream,就像在 many other examples on Whosebug.

中所做的那样

字节被发送到客户端,在那里它们被存储"locally"在最终用户的磁盘上。最终用户可能不会注意到该文件存储在本地,因为它存储在一个临时目录中。为什么存储在本地?因为 PDF 查看器需要磁盘上的文件。 PDF 查看器在最后开始阅读文件。这就是交叉引用 table 所在的位置。交叉引用 table 包含 PDF 中每个对象的字节偏移量。 PDF 查看器需要随机访问文件才能使用这些对象。另见 Disable save button in Adobe PDF reader and hide menu bar in IE window

如果使用 iText(就像你看起来那样),这个函数调用将采用任何类型的流,例如以下将 return 一个字节数组,然后您可以将其流式传输到您的客户端,而无需写入磁盘:

using (MemoryStream ms = new MemoryStream())
{
    Document doc = new Document(PageSize.A4, 50, 50, 15, 15);

    PdfWriter writer = PdfWriter.GetInstance(doc, ms);

    //You need to actually write something to the document here...

    return ms.ToArray();
}

您需要将文档保存到 Response.OutputStream,而不是将文档保存到文件。在编写 PDF 内容之前,您还应注意不要向浏览器写入任何内容。您还应该将响应流的内容类型设置为 PDF mime 类型。要成为 user-friendly,您应该添加一个 header 指定 PDF 文件的名称。这将确保浏览器弹出文件保存对话框。

Response.Clear();
// Tell server to cache output until asked to flush
Response.BufferOutput = true;
// Set the mime type - tells the browser that a
// PDF document is on the way
Response.ContentType = "application/pdf";
// Give the document a name
Response.AddHeader(
    "content-disposition",
    "attachment; filename=pdf_doc.pdf");

然后将您的 PDF 写入响应流,如 Paddy 所给出的那样。我认为您不需要将内存流更改为数组。我认为你应该能够直接将内存流写入 response.OutputStream.