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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/734404/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 23:06:50  来源:igfitidea点击:

Error using HttpWebRequest to upload files with PUT

c#networking

提问by SillyMonkey

We've got a .NET 2.0 WinForms app that needs to upload files to an IIS6 Server via WebDav. From time to time we get complaints from a remote office that they get one of the following error messages

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

  • The underlying connection was closed: an unexpected error occurred on send.
  • The underlying connection was closed: an unexpected error occurred on receive.
  • 基础连接已关闭:发送时发生意外错误。
  • 基础连接已关闭:接收时发生意外错误。

This only seems to occur with large files (~20Mb plus). I've tested it with a 40Mb file from my home computer and tried putting 'Sleep's in the loop to simulate a slow connection so I suspect that it's down to network issues at their end... but

这似乎只发生在大文件(~20Mb 以上)中。我已经用我家用电脑上的 40Mb 文件对其进行了测试,并尝试将“睡眠”置于循环中以模拟慢速连接,所以我怀疑这归结于网络问题......但是

  1. The IT at the remote office are no help
  2. I'd like to rule out the posibility my code is at fault.
  1. 远程办公室的 IT 无济于事
  2. 我想排除我的代码有问题的可能性。

So - can anybody spot any misakes or suggest any workarounds that might 'bulletproof' the code against this problem. Thanks for any help. Chopped down version of code follows:

所以 - 任何人都可以发现任何错误或建议任何可能针对此问题对代码进行“防弹”的解决方法。谢谢你的帮助。代码的删减版本如下:

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

采纳答案by kgiannakakis

Try setting KeepAliveto false:

尝试将KeepAlive设置为 false:

req.KeepAlive = false;

This will allow the connection to be closed and opened again. It will not allow to use a persistent connection. I found a lot of references in the Web that suggested this in order to solve a similar to yours error. This is a relevant link.

这将允许关闭并再次打开连接。它不允许使用持久连接。我在网上找到了很多建议这样做的参考资料,以解决与您类似的错误。这是一个相关链接

Anyway, it is not a good idea to use HTTP PUT (or HTTP POST) to upload large files. It will be better to use FTP or a download/upload manager. These will handle retries, connection problems, timeouts automatically for you. The upload will be faster too and you could also resume a stopped uploading. If you decide to stay with HTTP, you should at least try to add a retry mechanism. If an upload is taking too long, then there is a high probability that it will fail due to proxy, server timeout, firewall or what ever reason not to have with your code.

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

回答by david valentine

The size of the uploads might be limited.

上传的大小可能会受到限制。

See here for one discussion: http://www.codeproject.com/KB/aspnet/uploadlargefilesaspnet.aspx

请参阅此处的一个讨论:http: //www.codeproject.com/KB/aspnet/uploadlargefilesaspnet.aspx

回答by Luke Schafer

Maybe try using POST, but the real culprit is probably the content type.

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

Try setting

尝试设置

req.ContentType = "application/octet-stream";
req.ContentLength = inData.Length;

or look at the code in the accepted answer here: Upload files with HTTPWebrequest (multipart/form-data)

或查看此处接受的答案中的代码:使用 HTTPWebrequest (multipart/form-data) 上传文件

Both my example and the link I provided involve modifying the ContentType - my example is simpler but might not work, as most applications receiving files expect multipart

我的示例和我提供的链接都涉及修改 ContentType - 我的示例更简单但可能不起作用,因为大多数接收文件的应用程序都需要多部分

回答by Marc Gravell

To remove the risk of a bug in your code, try using WebClient:

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

using (WebClient client = new WebClient())
{
    client.UseDefaultCredentials = Program.WebService.UseDefaultCredentials;
    client.Credentials = Program.WebService.Credentials;
    client.UploadFile(uploadUrl, "PUT", localFile);
}

回答by Precipitous

Start by checking some basic configuration. The default values of either of the following may cause problems in file upload - including termination of the connection. I believe IIS 6 would never allow file upload > 2GB (even if it could complete, regardless of config). Msdn describes these nicely.

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

<httpRuntime executionTimeout = "30"  maxRequestLength="200"/>

EDIT: This is ASP.NET config, of course, which assumes you are running your own webdav server or a 3rd party serverwithin ASP.NET. If it's a different webdav server, you'll want to look for the equivalent.

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

回答by sesame

Please you check whether [Enable Http Keep-Alives] is set [on] at [Web Site] tab in IIS manager.

请检查 IIS 管理器中的 [网站] 选项卡中的 [启用 Http Keep-Alives] 是否设置为 [开启]。