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
Error using HttpWebRequest to upload files with PUT
提问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 文件对其进行了测试,并尝试将“睡眠”置于循环中以模拟慢速连接,所以我怀疑这归结于网络问题......但是
- The IT at the remote office are no help
- I'd like to rule out the posibility my code is at fault.
- 远程办公室的 IT 无济于事
- 我想排除我的代码有问题的可能性。
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] 是否设置为 [开启]。