我有一个Windows服务,它将文件上传到正在处理它们的其他网站。问题是,对于小文件,它工作正常,并且从那里获得响应,但是对于大文件(大约6分钟处理),它将永远处于等待模式。
以下是外部网站发布方法代码的一部分:
try
{
...
LogResults();
return string.Empty;
}
catch (Exception e)
{
return e.Message;
}
问题是我甚至可以看到大型文件的日志,所以这意味着网站总是返回值,但对于大型文件,我的Windows服务并不等待它们。
这是来自Windows服务的代码
var valuesp = new NameValueCollection
{
{ "AccountId", datafeed.AccountId }
};
byte[] resultp = UploadHelper.UploadFiles(url, uploadFiles, valuesp);
response = Encoding.Default.GetString(resultp);
UploadFiles
方法返回小文件的值,但永远等待大文件。
以下是UploadFiles的完整代码
public static byte[] UploadFiles(string address, IEnumerable<UploadFile> files, NameValueCollection values)
{
var request = WebRequest.Create(address);
request.Timeout = System.Threading.Timeout.Infinite; //3600000; // 60 minutes
request.Method = "POST";
var boundary = "---------------------------" +
DateTime.Now.Ticks.ToString("x", NumberFormatInfo.InvariantInfo);
request.ContentType = "multipart/form-data; boundary=" + boundary;
boundary = "--" + boundary;
using (var requestStream = request.GetRequestStream())
{
// Write the values
if (values != null)
{
foreach (string name in values.Keys)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.ASCII.GetBytes(string.Format("Content-Disposition: form-data; name=\"{0}\"{1}{1}", name,
Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer = Encoding.UTF8.GetBytes(values[name] + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
}
// Write the files
if (files != null)
{
foreach (var file in files)
{
var buffer = Encoding.ASCII.GetBytes(boundary + Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.UTF8.GetBytes(
string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"{2}", file.Name,
file.Filename, Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
buffer =
Encoding.ASCII.GetBytes(string.Format("Content-Type: {0}{1}{1}", file.ContentType,
Environment.NewLine));
requestStream.Write(buffer, 0, buffer.Length);
requestStream.Write(file.Stream, 0, file.Stream.Length);
buffer = Encoding.ASCII.GetBytes(Environment.NewLine);
requestStream.Write(buffer, 0, buffer.Length);
}
}
var boundaryBuffer = Encoding.ASCII.GetBytes(boundary + "--");
requestStream.Write(boundaryBuffer, 0, boundaryBuffer.Length);
}
using (var response = request.GetResponse())
using (var responseStream = response.GetResponseStream())
using (var stream = new MemoryStream())
{
responseStream.CopyTo(stream);
return stream.ToArray();
}
}
我在这里做错了什么?
编辑:在本地,它甚至可以处理7-8分钟。但在现场环境中并没有。它可以与主应用程序IIS设置相关吗?它可以与Windows服务器设置相关吗?
编辑2:远程服务器web.config httpRuntime设置
<httpRuntime enableVersionHeader="false" maxRequestLength="300000" executionTimeout="12000" targetFramework="4.5" />
答案 0 :(得分:6)
问题出在Azure Load Balancer上,默认情况下将Idle Timeout设置为4分钟。 Windows Azure博客的新帖子称,此超时现在可配置为4-30分钟之间的值
http://azure.microsoft.com/blog/2014/08/14/new-configurable-idle-timeout-for-azure-load-balancer/
然而,通过TCP发送额外的KeepAlive字节解决了这个问题,这告诉Load Balancer不会杀死请求。
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(address);
...
request.Proxy = null;
request.ServicePoint.SetTcpKeepAlive(true, 30000, 5000); //after 30 seconds, each 5 second
将Proxy设置为null(不使用代理)是强制操作,因为否则代理不会将tcp字节传递给服务器。
答案 1 :(得分:2)
使用符合RFC1867的方法上传文件
然后:
UploadFile[] files = new UploadFile[]
{
new UploadFile(fileName1),
new UploadFile(fileName2)
};
NameValueCollection form = new NameValueCollection();
form["name1"] = "value1";
form["name2"] = "xyzzy";
string response = UploadHelper.Upload(url, files, form);
这就是所有人!
编辑:
我使用上面的方法上传大小超过100MB的文件,我根本不使用ASP,它的工作非常完美!
答案 2 :(得分:2)
我有一个类似的问题,上传可以在本地工作,但在服务器上超时。这里有两件事情 - 我假设您正在谈论IIS7 +。如果没有,请告诉我,我很乐意删除我的答案。
首先,有ASP.NET查看此设置(在system.web
下):
<!-- maxRequestLength is in KB - 10 MB here. This is needed by ASP.NET. Must match with maxAllowedContentLength under system.webserver/security/requestLimits -->
<httpRuntime targetFramework="4.5" maxRequestLength="1048576" />
然后是IIS:
<system.webServer>
<security>
<requestFiltering>
<!-- maxAllowedContentLength in bytes - 10MB -->
<requestLimits maxAllowedContentLength="10485760" />
</requestFiltering>
</security>
<system.webServer>
您需要同时显示这两个设置以及匹配工作的限制。请注意,一个是KB,另一个是字节。
答案 3 :(得分:1)
可能是由IIS上传限制引起的? 在IIS7中,标准值为30MB。见MSDN
EDIT1: 请注意,如果您在1个请求中上传多个文件,则会增加大小。
EDIT2: 在所有MS示例中,始终只有一个 Stream.Write()。 在MSDN中声明:在返回Stream对象之后,您可以使用Stream.Write方法使用HttpWebRequest发送数据。我对这句话的解释是你应该调用只写一次()。将要发送的所有数据放入缓冲区,然后调用Write()。
答案 4 :(得分:1)
您是否检查过远程服务器上的IIS文件大小限制?默认为30MB,因此如果您尝试上传的文件大于该文件,则会失败。以下是如何更改上传限制(IIS7):http://www.web-site-scripts.com/knowledge-base/article/AA-00696/0/Increasing-maximum-allowed-size-for-uploads-on-IIS7.html
答案 5 :(得分:1)
您可以使用AsyncCallback技术完成此任务。
当异步方法完成处理时,会自动调用AsyncCallback方法,其中可以执行后处理stmts。使用此技术,无需轮询或等待异步线程完成。
您可以从此链接中找到更多详细信息
答案 6 :(得分:1)
您应该将此executionTimeout="12000"
更改为executionTimeout="360000"
,这意味着将执行超时从2分钟更改为6分钟。