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

时间:2013-01-30 16:54:32

标签: c# javascript asp.net download

我有一个网页,用户可以通过ASP.NET Web处理程序(.ashx)下载PDF文件。它的实现类似于question中的答案。我遇到的问题是当我在JavaScript中执行此操作时window.top.location.href = url;我无法真正控制在处理程序中抛出异常时会发生什么。当一切正常时,用户体验是他们基本上停留在他们所在的页面上,并且浏览器告诉他们他们可以下载PDF文件。但是,当处理程序中抛出异常时,它们会被重定向到处理程序的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()抛出异常时会出现问题。我们正在尽我们所能阻止GetPDFData()抛出异常,但它是从用户输入生成的,所以我们也在这里处理它,以防有时我们不能/无法预测哪些会产生错误。

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

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));
    }
}

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

2 个答案:

答案 0 :(得分:7)

首先在this answer of mine上,用户询问如何使用javascript进行下载。但是如果你有链接,你不需要将它添加到javascript,你也可以使用常规下载链接添加它。

现在很多网站都使用一个带有一些文字的页面,上面写着“,现在你的下载将在几秒钟内开始。如果没有开始,请点击这里bla bla bla ”。其中一个原因与您的相似,用户必须知道某些内容会在几秒钟后开始下载,如果没有,那么用户就会明白其他额外消息存在问题。

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

  

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

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

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

替代异常,您可以尝试使用

将其重定向到错误页面
Response.Redirect("errorpage.aspx");

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

您还可以尝试将简单消息显示为

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

答案 1 :(得分:2)

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

context.Response.Clear();
context.Response.Write("<script>alert('" + GetErrorMessage(e) + "');</script>");

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

context.Response.Clear();
context.Response.Write("<script>window.parent.someFunction('" + GetErrorMessage(e) + "');</script>");

以下是我在SO上发现的一个例子:Retrieving HTTP status code from loaded iframe with Javascript

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