C# 使用HttpWebRequest上载带有PUT的文件时出错

C# 使用HttpWebRequest上载带有PUT的文件时出错,c#,networking,C#,Networking,我们有一个.NET 2.0 WinForms应用程序,需要通过WebDav将文件上载到IIS6服务器。我们不时收到远程办公室的投诉,他们收到以下错误消息之一 基础连接已关闭: 发送时发生意外错误 基础连接已关闭: 上发生意外错误 接受 这似乎只发生在大文件(~20Mb以上)中。我用家用电脑上的40Mb文件对它进行了测试,并尝试将“睡眠”放在循环中以模拟慢速连接,因此我怀疑这最终是由于网络问题造成的。。。但是 远程办公室的IT也帮不了什么忙 我想排除我的代码出错的可能性 那么-有人能发现任何错

我们有一个.NET 2.0 WinForms应用程序,需要通过WebDav将文件上载到IIS6服务器。我们不时收到远程办公室的投诉,他们收到以下错误消息之一

  • 基础连接已关闭: 发送时发生意外错误
  • 基础连接已关闭: 上发生意外错误 接受
这似乎只发生在大文件(~20Mb以上)中。我用家用电脑上的40Mb文件对它进行了测试,并尝试将“睡眠”放在循环中以模拟慢速连接,因此我怀疑这最终是由于网络问题造成的。。。但是

  • 远程办公室的IT也帮不了什么忙
  • 我想排除我的代码出错的可能性
  • 那么-有人能发现任何错误或提出任何可能“防弹”代码解决此问题的解决方法吗。谢谢你的帮助。代码的简化版本如下:

        public bool UploadFile(string localFile, string uploadUrl)
        {
            HttpWebRequest req = (HttpWebRequest)WebRequest.Create(uploadUrl);
    
            try
            {
                req.Method = "PUT";
                req.AllowWriteStreamBuffering = true;
                req.UseDefaultCredentials = Program.WebService.UseDefaultCredentials;
                req.Credentials = Program.WebService.Credentials;
                req.SendChunked = false;
                req.KeepAlive = true;
                Stream reqStream = req.GetRequestStream();
                FileStream rdr = new FileStream(localFile, FileMode.Open, FileAccess.Read);
                byte[] inData = new byte[4096];
                int bytesRead = rdr.Read(inData, 0, inData.Length);
    
                while (bytesRead > 0)
                {
                    reqStream.Write(inData, 0, bytesRead);
                    bytesRead = rdr.Read(inData, 0, inData.Length);
                }
    
                reqStream.Close();
                rdr.Close();
    
                System.Net.HttpWebResponse response = (HttpWebResponse)req.GetResponse();
                if (response.StatusCode != HttpStatusCode.OK && response.StatusCode!=HttpStatusCode.Created)
                {
                    MessageBox.Show("Couldn't upload file");
                    return false;
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString());
                return false;
            }
            return true;
        }
    

    上载的大小可能会受到限制

    请参见此处的一个讨论:

    可能尝试使用POST,但真正的罪魁祸首可能是内容类型

    尝试设置

    req.ContentType = "application/octet-stream";
    req.ContentLength = inData.Length;
    
    或者在此处查看已接受答案中的代码:

    我的示例和我提供的链接都涉及到修改ContentType—我的示例比较简单,但可能不起作用,因为大多数接收文件的应用程序都希望使用multipart,请尝试将设置为false:

    req.KeepAlive = false;
    
    这将允许再次关闭和打开连接。它将不允许使用。我在网上找到了很多建议这一点的参考资料,以解决一个类似于你的错误。这是一个相关的问题


    无论如何,使用HTTPPUT(或HTTPPOST)上传大文件不是一个好主意。最好使用FTP或下载/上传管理器。这些将为您自动处理重试、连接问题和超时。上传速度也会更快,您还可以恢复已停止的上传。如果您决定继续使用HTTP,至少应该尝试添加重试机制。如果上载时间过长,则很有可能由于代理、服务器超时、防火墙或其他原因导致上载失败。

    要消除代码中的错误风险,请尝试使用:


    首先检查一些基本配置。以下任一项的默认值都可能导致文件上载出现问题,包括连接终止。我相信IIS 6永远不会允许文件上传大于2GB(即使它可以完成,无论配置如何)

    
    

    编辑:这当然是ASP.NET配置,它假设您正在运行自己的webdav服务器或ASP.NET中的。如果它是不同的webdav服务器,则您需要查找等效服务器。

    请检查IIS管理器中的[Web站点]选项卡上是否设置了[Enable Http Keep Alives]。

    不是这样,WebDAV传输不会命中ASP.NET,我可以自己从不同的远程网络上传相同的文件。什么是WebDAV客户端和服务器?这不会导致间歇性问题。URL必须包含目标文件名吗?我希望如此,但这取决于服务器。@MarcGravel,在您的示例中,什么是有效的上传URL?uploadUrl指向任何目标方法,或指向目标文件夹,在该文件夹中它将被放置。@KumarHarsh这完全由web应用程序决定;
    PUT
    请求只是一个带有不同动词的常规HTTP请求(而不是
    GET
    HEAD
    POST
    等)。web应用程序的作用是:完全取决于应用程序。
    using (WebClient client = new WebClient())
    {
        client.UseDefaultCredentials = Program.WebService.UseDefaultCredentials;
        client.Credentials = Program.WebService.Credentials;
        client.UploadFile(uploadUrl, "PUT", localFile);
    }
    
    <httpRuntime executionTimeout = "30"  maxRequestLength="200"/>