从ASP.NET Web处理程序(.ashx)下载文件时的error handling

我有一个网页,用户可以通过ASP.NET Web处理程序( .ashx )下载PDF文件。 它的实现就像这个问题的答案一样。 我遇到的问题是当我做这个window.top.location.href = url; 在我的JavaScript中,如果处理程序中抛出exception,我无法真正控制会发生什么。 当一切正常时,用户体验是他们基本上停留在他们所在的页面上,浏览器告诉他们可以下载PDF文件。 但是,当处理程序中抛出exception时,它们会被重定向到处理程序的URL并显示一个空白页面。

以下是一些示例代码,使其更加清晰:

JavaScript的:

 function openPDF() { var url = GeneratePDFUrl(); window.top.location.href = url; } 

处理器:

 public override void Process(HttpContext context) { byte[] pdfdata = GetPDFData(); context.Response.ContentType = "application/pdf"; context.Response.AddHeader("content-disposition", "attachment; filename=\"" + GetPDFFileName() + "\""); context.Response.AddHeader("content-length", pdfdata.Length.ToString()); context.Response.BinaryWrite(pdfdata); } 

GetPDFData()抛出exception时会发生此问题。 我们正在尽我们所能阻止GetPDFData()抛出exception,但它是从用户输入生成的,所以我们也在这里处理它,以防有时我们不能/无法预测哪些会产生错误。

这是我提出的一个解决方案,但它显示用户错误文本(而不是空白页)

 public override void Process(HttpContext context) { try { byte[] pdfdata = GetPDFData(); WritePDF(pdfdata, GetPDFFileName()); // Executes code in example above } catch (Exception e) { context.Response.Clear(); context.Response.Write(GetErrorMessage(e)); } } 

理想情况下,我想向用户显示一个弹出窗口,以便他们留在他们所在的页面上。

首先,在我的这个答案中 ,用户询问如何使用javascript进行下载。 但是如果你有链接,你不需要将它添加到javascript,你也可以使用常规下载链接添加它。

现在很多网站使用的页面上都有一些文字说“ 现在你的下载将在几秒钟内开始。如果没有开始请点击这里bla bla bla ”。 其中一个原因与您的类似,用户必须知道某些内容将在几秒钟内启动下载,如果没有,则用户必须了解其他额外消息存在问题。

一般情况下,当您要发送文件进行下载时,您不再在页面中,您无法在下载过程中发送消息,或者当文件以pdf结尾时,则可能不会显示任何内容在网页上。 因此,从我的观点来看,如果你确实遇到问题并抛出exception,你需要设计一些步骤来告知用户出现问题的方法 – 比如中间页面告知用户“现在你要收到一个文件 – 如果文件没有在几秒钟内开始下载,请执行此操作“

但是,当处理程序中抛出exception时,它们会被重定向到处理程序的URL并显示一个空白页面。

为了避免该黑色页面,出错时您可以返回该代码并且用户保持在页面上,但仍然没有收到任何错误消息。

 Response.TrySkipIisCustomErrors = true; Response.Status = "204 No Content"; Response.StatusCode = 204; Response.End(); 

替代exception您可以尝试使用它将其重定向到错误页面

 Response.Redirect("errorpage.aspx"); 

也许你可以发送和一些错误ID。

您也可以尝试只显示一条简单的消息

 context.Response.ContentType = "text/html"; context.Response.Write("Error downloading file - Please contact with us"); 

如何设置隐藏的iframe的src,而不是设置窗口的href。 然后,您可以使用隐藏的iframe中的返回值进行一些欺骗,例如:

 context.Response.Clear(); context.Response.Write(""); 

这个粗略的例子只会提醒错误信息。 如果你在同一个域名(我怀疑你是那个!)那么你可以更聪明,而不是提醒,在父母中调用一个方法,例如

 context.Response.Clear(); context.Response.Write(""); 

这是我在SO上发现的一个例子: 使用Javascript从加载的iframe中检索HTTP状态代码

这是一个上传,而不是下载,但相同的概念。