【问题标题】:How do I handle error writing file in ASP .NET?如何在 ASP .NET 中处理错误写入文件?
【发布时间】:2013-10-01 11:52:52
【问题描述】:

我有一个应该传输文件的页面

所有代码都包含在一个 try/catch 异常块中

我使用 Response.TransmitFile 来实际写入文件,当它失败时(在我的情况下由于权限问题),对客户端的响应是一些自动生成的 html,其中详细说明了错误,其中一部分说:“未处理在执行当前 Web 请求期间产生了异常。”

为什么说未处理的异常?

我发现了错误,因为标头已更改为 text/html 而不是八位字节流,如果文件成功继续,它将被设置为。但似乎对 TransmitFile 的调用将自己的内容写入响应,然后刷新它,这真的是不可取的!

我能做什么?

try
{
    String targetFile = Request.Form["filePath"];
    if (targetFile == null) throw new Exception("No filename provided");
    FileInfo file = new FileInfo(targetFile); 
    if (!file.Exists)
    {
        // file not found error
        throw new Exception("File not found");
    }

        Response.ContentType = "APPLICATION/OCTET-STREAM";
        Response.AppendHeader("Content-Disposition", "Attachment; Filename=\"" + Path.GetFileName(targetFile) + "\"");

        Response.TransmitFile(file.FullName);

} 
catch (Exception e) 
{
    Response.ClearHeaders();
    Response.ClearContent();
    Response.ContentType = "text/html";

    StringBuilder sb = new StringBuilder();
    // I write my own response in sb - I never see this content sent back!!
    Response.Write(sb.ToString());
    Response.Flush();
}

【问题讨论】:

  • file.FullName的值是多少?
  • 它是文件的 Windows UNC 路径,即 \\server\folder\file.ext
  • Response.TransmitFile 下面还有其他代码吗?另外,为什么在附加标头和传输文件之前不清除响应?

标签: asp.net


【解决方案1】:

Response.TransmitFile 将文件直接写入响应流而不缓冲它。

由于它已经被写入并发送到客户端,因此您无法在 catch 块中将其取回/清除标头等 - 一些响应已经发送到客户端!

作为替代方案,您可以使用 Response.WriteFile 将文件缓冲到内存(前提是您的 Response.Buffer 属性或 Response.BufferOutput 设置为 true)。这应该允许您在出现异常时“收回”。

请记住,这可能会对非常大的文件产生性能影响,因此请为您的方案选择最佳方法。

http://msdn.microsoft.com/en-us/library/system.web.httpresponse.buffer.aspx

http://msdn.microsoft.com/en-us/library/system.web.httpresponse.writefile.aspx

http://msdn.microsoft.com/en-us/library/12s31dhy.aspx

【讨论】:

  • 不用担心。没有什么可以替代测试,但我猜想您在传输之前尝试读取文件的第一个字节的方法可能会优于 WriteFile 方法。对于较大的文件,我通常更喜欢 TransmitFile。
【解决方案2】:

这是我为使其再次工作所做的工作。不过,这似乎是一种黑客行为……呃!

using (FileStream stream = file.OpenRead())
{

byte[] buffer = new byte[1];
int read = stream.Read(buffer, 0, buffer.Length);

if (read <= 0)
{
    throw new Exception("Access denied");
}

Response.ContentType = "APPLICATION/OCTET-STREAM";
Response.AppendHeader("Content-Disposition", "Attachment; Filename=\"" + Path.GetFileName(targetFile) + "\"");

Response.TransmitFile(file.FullName);


}  

它现在可以按我的意图工作...如果它没有读取任何字节,我认为这是一个访问被拒绝错误并转到我的 catch 块并写我想要的,而不是一些预先生成的 IIS html 破坏过程...

(我需要使用 jQuery postMessage 响应,因为这是一个 AJAX 请求)

【讨论】:

    猜你喜欢
    • 2016-06-22
    • 1970-01-01
    • 2017-06-12
    • 2016-05-30
    • 2017-04-28
    • 1970-01-01
    • 2011-03-18
    • 2020-07-01
    • 1970-01-01
    相关资源
    最近更新 更多