【问题标题】:Webclient using download file to grab file from server - handling exceptionsWebclient 使用下载文件从服务器抓取文件 - 处理异常
【发布时间】:2010-03-15 03:14:15
【问题描述】:

我有一个 Web 服务,我在其中操作 POST 和 GET 方法,以促进客户端/服务器样式架构中某些文件的上传/下载功能。基本上,用户可以点击按钮下载特定文件,在应用程序中进行一些更改,然后点击上传按钮将其发回。

我遇到的问题是下载。假设用户需要 3 个文件 1.txt、2.txt 和 3.txt。除了2.txt在服务器上不存在。

所以我有类似(在服务器端)的代码:

public class HttpHandler : IHttpHandler
{

    public void ProcessRequest
    {
       if (context.Request.HttpMethod == "GET")
       {
          GoGetIt(context)
       }
    }

private static void GoGetIt(HttpContext context)
{
     var fileInfoOfWhereTheFileShouldBe = new FileInfo(......);

     if (!fileInfoOfWhereTheFileShouldBe.RefreshExists())
     {
          //Remove this line below
          //throw new Exception("Oh dear the file doesn't exist");

          //Replace with a force return of whichever code I chose e.g. 200
          ??...
     }

    ...

所以我遇到的问题是,当我运行应用程序时,我在客户端使用 WebClient 来使用 DownloadFile 方法,然后使用上面的代码,我得到:

WebException 未处理:远程服务器返回错误:(500) 内部服务器错误。

(调试时)如果我附加到浏览器并使用http://localhost:xxx/1.txt,我可以单步执行服务器端代码并​​按预期抛出异常。所以我想我想知道如何正确处理客户端的内部服务器错误,这样我就可以返回一些有意义的东西,比如“文件不存在”。一种想法是围绕WebClient.DownloadFile(address, filename) 方法使用try catch,但我不确定这是唯一会发生的错误,即文件不存在。

编辑:使用 HttpResponse 遵循解决方案

那么如果我要使用 HttpResponse,我能得到一些关于如何开始的建议吗?

我从客户端删除异常抛出,并替换为自定义 HttpResponse?所以基本上我想我会选择一个要使用的代码,比如 200,并在上面的 if 语句中强制返回代码 200。见评论。

然后在客户端只需使用If (Response.StatusCode == 200) 并做我想做的任何事情(通知用户文件不存在)

我的思路是正确的?

编辑 2:

我一直在尝试在我的文件复制方法周围使用 try catch,然后在 catch 中设置状态代码或状态描述,但这会在设置状态描述时引发异常......像这样:

context.Response.StatusDescription = ex.ToString();
context.Response.Status = ex.ToString();

ArgumentOutOfRangeException - 指定的参数超出了有效值的范围。

【问题讨论】:

    标签: c# .net visual-studio-2008 webclient ihttphandler


    【解决方案1】:

    如果您正在编写IHttpHandler 接口,则不应在该代码上引发异常。从来没有!

    改为使用Response.StatusCodeResponse.StatusDescriptionmeaningful information 返回给客户端。

    只让系统抛出异常,因为那样,它真的会成为您的代码的异常。

    编辑添加

    回答您的编辑时,如果在服务器端找不到文件,我会返回 404 状态码。并让客户处理。

    但是,正如您所说,您正在处理 Web 服务,因此,我只需在标头中添加一些额外的响应,以便更好地指定客户端应用程序的服务器端真正发生的事情。

    编辑添加

    Response.Status 是整数。这就是您收到ArgumentOutOfRangeException 的原因。

    确保 Status 是有效的HTTP return codes 之一。

    【讨论】:

    • 这是出于安全原因吗? IHttpHandler 中的异常有什么问题?
    • @baron:它们不会以任何有意义的方式传播给客户端。
    • 我不明白当它在(客户端)WebClient.DownloadFile(URLofTxt); 上中断(WebException 未处理)时,标题将如何提供帮助你也可以展示一些如何设置响应的代码,我不能解决这个问题或在您的链接中找到任何好的示例。
    • 在查看您的答案时,我意外地否决了您的答案(在我已经投了赞成票之后)。现在stackoverflow迟迟不会让我解决这个问题,因为“投票太旧而无法更改,除非这个答案被编辑”,尽管事实上我试图在意外更改为首先投票后立即将其更改回来。那又怎样——我迟到了半秒?不知怎的,我觉得这很难相信。嗯。对不起。
    【解决方案2】:

    不要抛出异常,而是将异常记录在文本文件或事件日志中,以便您可以准确地看到错误发生时发生的情况。

    这里是事件记录的示例代码http://support.microsoft.com/kb/307024。 保存在文本文件中

        public void WriteExceptionToDisk(Exception exceptionLog)
        {
    
            string loggingname = @"c:\Exception-" + DateTime.Today.Month.ToString()
                                 + "-" + DateTime.Today.Day.ToString() + "-" +
                                 DateTime.Today.Year.ToString() + ".txt";
            // Put the exception some where in the server but
            // make sure Read/Write permission is allowed.
            StringBuilder message = new StringBuilder();
            if (exceptionLog != null)
            {
                message.Append("Exception Date and Time ");
                message.AppendLine(); 
                message.Append("   ");
                message.Append(DateTime.Today.ToLongDateString() + " at ");
                message.Append(DateTime.Now.ToLongTimeString());
                message.AppendLine();
                message.Append("Exception Message ");
                message.AppendLine(); message.Append("   ");
                message.Append(exceptionLog.Message);
                message.AppendLine();
                message.AppendLine("Exception Detail ");
                message.AppendLine();
                message.Append(exceptionLog.StackTrace);
                message.AppendLine();
            }
            else if (message == null || exceptionLog == null)
            {
                message.Append("Exception is not provided or is set as null.Please pass the exception.");
            }
    
            if (File.Exists(loggingname))// If logging name exists, then append the exception message
            {
    
                File.AppendAllText(loggingname, message.ToString());
            }
            else
            {
                // Then create the file name
                using (StreamWriter streamwriter = File.CreateText(loggingname))
                {
                    streamwriter.AutoFlush = true;
                    streamwriter.Write(message.ToString());
                    streamwriter.Close();
                }                 
            }
        }
    

    【讨论】:

    • -1: 1) StreamWriter 需要在using 块中,否则如果抛出异常,资源将被泄露。 2)通过字符串连接构建消息。
    • @约翰桑德斯。为什么 StreamWriter 应该使用 block.I 刚刚明确关闭?
    • 因为如果抛出异常WHILEStreamWriter正在被使用,那么资源将被泄露。通过用using 子句包装它,您可以确保即使抛出异常,资源也会被正确清除。
    • @Paulo Santos - 感谢您的详细解释。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-24
    • 1970-01-01
    • 2015-10-08
    • 1970-01-01
    • 2012-08-15
    相关资源
    最近更新 更多