【问题标题】:Delete dynamically generated PDF file immediately after it has been displayed to user动态生成的 PDF 文件显示给用户后立即删除
【发布时间】:2010-10-14 01:02:02
【问题描述】:

我正在使用 ITextSharp 和 ASP.NET 1.1 动态创建 PDF 文件。我的流程如下-

  • 在服务器上创建文件
  • 将浏览器重定向到新创建的 PDF 文件,以便向用户显示

我想做的是在用户浏览器中显示 PDF 后立即从服务器中删除它。 PDF 文件很大,因此不能将其保存在内存中,需要对服务器进行初始写入。我目前正在使用定期轮询文件然后删除它们的解决方案,但我更喜欢在文件下载到客户端计算机后立即删除文件的解决方案。有没有办法做到这一点?

【问题讨论】:

  • 您可以检查对这个唯一命名的 PDF 文件的请求是否使用 200 代码提供服务,并在那时获取它;但是,您最初的解决方案听起来“足够好”。您能否告知为什么您当前的解决方案不起作用,以便我们提出更好的解决方案?

标签: c# asp.net vb.net pdf-generation


【解决方案1】:

您可以使用自己的 HttpHandler 自己提供文件,而不是将浏览器重定向到创建的文件。然后,您可以在提供文件后立即删除该文件,甚至可以在内存中创建该文件。

将PDF文件直接写入客户端:

public class MyHandler : IHttpHandler {
    public void ProcessRequest(System.Web.HttpContext context) {
        context.Response.ContentType = "application/pdf";
        // ...
        PdfWriter.getInstance(document, context.Response.OutputStream);
        // ...

或读取已经生成的文件“文件名”,提供文件,删除它:

context.Response.Buffer = false;
context.Response.BufferOutput = false;
context.Response.ContentType = "application/pdf";

Stream outstream = context.Response.OutputStream;
FileStream instream = 
    new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read);

byte[] buffer = new byte[BUFFER_SIZE];
int len;
while ((len = instream.Read(buffer, 0, BUFFER_SIZE)) > 0) {
    outstream.Write(buffer, 0, len);
}
outstream.Flush();
instream.Close();

// served the file -> now delete it 
File.Delete(filename);

我没有尝试这个代码。这就是我认为它会起作用的方式......

【讨论】:

    【解决方案2】:

    受 f3lix 回答的启发(感谢 f3lix!)我想出了以下 VB.net 代码 -

    HttpContext.Current.Response.ClearContent()
    HttpContext.Current.Response.ClearHeaders()
    HttpContext.Current.Response.ContentType = "application/pdf"
    HttpContext.Current.Response.TransmitFile(PDFFileName)
    HttpContext.Current.Response.Flush()
    HttpContext.Current.Response.Close()
    File.Delete(PDFFileName)
    

    这似乎有效 - 我使用的“WriteFile”方法是否比 f3lix 使用的流方法效率低?有没有比我们的任何一种解决方案都更有效的方法?

    编辑(19/03/2009)基于下面的 cmets,我已将“WriteFile”方法更改为“TransmitFile”,因为它似乎将文件以块的形式发送到客户端,而不是之前将整个文件写入网络服务器的内存发送。更多信息可以在here找到。

    【讨论】:

    • 您应该改用 TransmitFile。 WriteFile 将整个文件加载到内存中 - TransmitFile 流式传输它。
    • 此外,设置 Response.Buffer = true 有点违背 TransmitFile,但我不确定 TransmitFile 是否会忽略 Buffer 参数。
    【解决方案3】:

    解决办法:

    Response.TransmitFile(PDFFileName)
    Response.Flush()
    Response.Close()
    File.Delete(PDFFileName)
    

    对我来说根本不起作用(文件永远不会发送给客户)。读取字节数组并调用 Response.BinaryWrite 也不是一种选择,因为文件可能很大。这是唯一的 hack 来启动一个等待文件被释放然后删除它的异步进程吗?

    【讨论】:

      【解决方案4】:

      或者你可以直接将它返回给浏览器而不写入磁盘:

      byte[] pdf;
      
      using (MemoryStream ms = new MemoryStream()) {
          Document doc = new Document();
          PdfWriter.GetInstance(doc, ms);
          doc.AddTitle("Document Title");
          doc.Open();
          doc.Add(new Paragraph("My paragraph."));
          doc.Close();
          pdf = ms.GetBuffer();
      }
      
      Response.ContentType = "application/pdf";
      Response.AddHeader("Content-Disposition", "attachment;filename=MyDocument.pdf");
      Response.OutputStream.Write(pdf, 0, pdf.Length);
      

      【讨论】:

        猜你喜欢
        • 2017-09-09
        • 2019-01-07
        • 2022-10-14
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-05-03
        相关资源
        最近更新 更多