【问题标题】:View PDF in Browser in new window on button click and delete file在按钮单击和删除文件时在新窗口中的浏览器中查看 PDF
【发布时间】:2012-08-03 19:03:24
【问题描述】:

我在删除仅为发送带有附件的电子邮件然后在浏览器中查看而创建的文件时遇到问题。现在我需要删除这个文件,因为它只是为了发送电子邮件而创建的。我该怎么做。

这是我到目前为止所得到的。

public void SendEmail()
 {
    EmailClient.Send(mailMessage);

    //View PDF Certificate in Browser
    ViewPDFinBrowser((string)fileObject);

    DeleteGeneratedTempCertificateFile((string)fileObject));
}    

public void ViewPDFinBrowser(string filePath)
  {
     PdfReader reader = new PdfReader(filePath);
     MemoryStream ms = new MemoryStream();

     PdfStamper stamper = new PdfStamper(reader, ms);
     stamper.ViewerPreferences = PdfWriter.PageLayoutSinglePage | PdfWriter.PageModeUseThumbs;
     stamper.Close();

     Response.Clear();
     Response.ContentType = "application/pdf";
     Response.OutputStream.Write(ms.GetBuffer(), 0, ms.GetBuffer().Length);
     Response.OutputStream.Close();
     HttpContext.Current.ApplicationInstance.CompleteRequest();

  }

  public static void DeleteGeneratedTempCertificateFile(Object fileObject)
  {
      string filePath = (string)fileObject;
      if (File.Exists(filePath))
      {
          File.Delete(filePath);
      }
  }

以下是我调用 SendEmail() 时需要的步骤

1) 发送带有附件的电子邮件 --> 创建临时文件 2)在浏览器中查看临时文件 3)删除临时文件

我可以理解,只要文件在响应对象中,我就无法对它做任何事情,因为我收到错误消息(“文件被另一个进程使用)。如果我关闭响应流,那么文件将被删除,但是然后浏览器就看不到了。

我在想,如果我能设法在单击按钮时以某种方式打开文件以在新窗口中的浏览器中查看,我将能够删除该文件。 或者 我想我可以在 10 分钟后删除文件。因为用户不会在现场查看 PDF 超过 1-2 分钟。

请用示例代码告诉我一个解决方案。

感谢您的时间和帮助。

【问题讨论】:

  • 为什么需要写文件呢?我直接从MemoryStreamMailMessage 创建了附件。
  • 我已经尝试过了,可以使用内存流在浏览器中查看文件。但是以某种方式使用 meorystream,我无法将文件附加到 MailMessage.. 我只想使用这种方法。但它不工作,所以这就是为什么我选择这种方法.. 请帮助
  • 您确定需要在添加到附件之前重置MemoryStream 吗?调试过了,确实不为空?
  • 是的,要获取文件作为附件,我们需要将内存流位置设置为 0.. 这就是谷歌搜索返回给我的结果。

标签: c# asp.net


【解决方案1】:

正如其他人所说,最好按原样使用 MemoryStream 而不将临时文件写入磁盘。有时 3rd 方组件的实现不允许这样做,在这种情况下,在编写 PDF 文件的二进制内容后,一定要调用 close (和/或可能处置,总是检查 MSDN 或 3rd 方 API 文档 .Close () 实际上确实如此)到所有不再需要的流。在您的情况下,在完成 http 请求后关闭 msreader

在大多数情况下,请考虑实现 using 模式。有关详细信息,请参阅http://msdn.microsoft.com/en-us/library/aa664736.aspx。但是请记住,这种方法也有一些警告,例如在 WCF 客户端中,这可能会导致异常(因此实际上并未在 using 子句中处理所有内容)。

另外,请记住任何并发问题。保持临时文件名足够随机,并考虑文件已经存在于本地磁盘上的情况(即操作失败并且不向请求者不应该看到的请求发送二进制文件等)。

【讨论】:

  • 如果您可以使用Memorystream 看到我之前的帖子,我似乎无法以某种方式附加文件。请让我知道我做错了什么..
  • 传递 MemoryStream(并在返回此类句柄之前关闭相关的读取器/写入器)不是一个好主意。以一种方法创建 PDF 二进制数据,然后按原样返回该数据,所有不必要的流在不需要后立即关闭。简化,但仍然:仅当需要在方法之间以任何方式处理/编辑/转换/等流时,使用流才是理想的。否则,您只需要跟踪关闭(和倒带,即重新定位)所有打开的流的位置,这些位置首先调用创建它们的方法。
  • 所以你建议传递流可能会关闭流,所以我无法附加文件。
  • 是的。您可以通过调试来验证这一点:只需在尝试返回之前立即检查流是否为空。如果是这样,请尝试如果您不关闭流会发生什么。如果它有效,那么......好吧......你有工作代码,期待现在你需要处理流的关闭(在其他地方)。如果确实如此,我建议重写代码以不传递流。
  • 我添加了一个条件来检查 ms != null .. 并且它不是 null 但不知何故它没有在浏览器中呈现。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-08-03
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多