(转)利用HttpWebRequest上传文件应该注意的问题
2009-04-08 16:00
627 查看
最近,在做一个Online Video的公司内部系统时,遇到一个利用HttpWebRequest上传文件时的问题,现象如下:
1、上传30M以下的文件速度很快,大概2-3m。
2、上传90-100M的文件速度在3-5m。
3、上传30M-90M这个区间的任意大小的文件都失败,用时100-101m,错误描述:The operation is time out。
4、将同样的文件用相同的程序,放在另外一台机器上work一切正常。
这个错误是framwork底层抛出来的,若根据这个错误描述查找问题是无法真正解决问题的。
首先,我将代码show出来,大家看看有没有问题:
private static void UploadFile(Stream postedStream, string fileName,
string uploadURL, string fileGroup, string fileType,
string specialPath, string userName, string uploadType)
{
if (string.IsNullOrEmpty(uploadURL))
throw new Exception("Upload Web URL Is Empty.");
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uploadURL);
//Our method is post, otherwise the buffer (postvars) would be useless
webRequest.Method = WebRequestMethods.Http.Post;
// Proxy setting
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
webRequest.Proxy = proxy;
//We use form contentType, for the postvars.
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Headers.Add("FileGroup", fileGroup);
webRequest.Headers.Add("FileType", fileType);
webRequest.Headers.Add("UploadType", uploadType);
webRequest.Headers.Add("FileName", fileName);
webRequest.Headers.Add("UserName", userName);
webRequest.Headers.Add("SpecialFolderPath", specialPath);
using (Stream requestStream = webRequest.GetRequestStream())
{
FileUtility.CopyStream(postedStream, requestStream);
}
try
{
webRequest.GetResponse().Close();
}
catch (WebException ex)
{
HttpWebResponse response = ex.Response as HttpWebResponse;
if (response != null)
{
throw new WebException(response.StatusDescription, ex);
}
throw ex;
}
catch (Exception exception)
{
throw exception;
}
}
下面,我们来分析上述的现象,发现根本无法找到问题的根本,一头雾水。首先,可以肯定失败的原因是和文件的大小有关的,但是,发生错误的文件大小却是在一个区间段里的,这就无法解释了。然后,我们发现time out的时间都是刚刚超出100m,具体在100-101m之内;这个时间是在需要发送的Request里设的:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uploadURL);
....
webRequest.Timeout = 1000;//默认为100m,单位为毫秒
那我们就决定将这个时间设的更长一些,但是,根本没用。其实,我们能基本肯定问题不是在这里,因为在上传90M这么大的文件都能很轻易成功,根据这点我们就有理由怀疑问题不是在这里。但是,这种莫名的问题让我们无法理解,接着,我们就像没头苍蝇一样,将所有可以设置time out的地方都设了,比如IIS,接受上传的WebSite里的config里,结果,大家可想而知。
在代码层面我们已经找不到任何办法了,然后,我们只能怀疑是这台服务器的环境有问题,就把问题抛给了公司的IT。可怜了这些IT,怎么可能找到问题!
后来,美国的同事与微软的工作人员一起联调,终于发现了问题的所在,是我们在发送Request的时候没有精确的指定这个Request的ContentLength,导致Framework底层无法知道你什么时候需要终止这个Request,我们只要在上面的代码中增加这段话:
...
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = postedStream.Length;
...
经过测试,发现果然是这个原因。但是,我们就有个问题,微软为什么不在底层处理好这些呢?我们认为微软在底层更能拿到我们的Request的长度,而且更容易包装,更利于使用。
1、上传30M以下的文件速度很快,大概2-3m。
2、上传90-100M的文件速度在3-5m。
3、上传30M-90M这个区间的任意大小的文件都失败,用时100-101m,错误描述:The operation is time out。
4、将同样的文件用相同的程序,放在另外一台机器上work一切正常。
这个错误是framwork底层抛出来的,若根据这个错误描述查找问题是无法真正解决问题的。
首先,我将代码show出来,大家看看有没有问题:
private static void UploadFile(Stream postedStream, string fileName,
string uploadURL, string fileGroup, string fileType,
string specialPath, string userName, string uploadType)
{
if (string.IsNullOrEmpty(uploadURL))
throw new Exception("Upload Web URL Is Empty.");
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uploadURL);
//Our method is post, otherwise the buffer (postvars) would be useless
webRequest.Method = WebRequestMethods.Http.Post;
// Proxy setting
WebProxy proxy = new WebProxy();
proxy.UseDefaultCredentials = true;
webRequest.Proxy = proxy;
//We use form contentType, for the postvars.
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.Headers.Add("FileGroup", fileGroup);
webRequest.Headers.Add("FileType", fileType);
webRequest.Headers.Add("UploadType", uploadType);
webRequest.Headers.Add("FileName", fileName);
webRequest.Headers.Add("UserName", userName);
webRequest.Headers.Add("SpecialFolderPath", specialPath);
using (Stream requestStream = webRequest.GetRequestStream())
{
FileUtility.CopyStream(postedStream, requestStream);
}
try
{
webRequest.GetResponse().Close();
}
catch (WebException ex)
{
HttpWebResponse response = ex.Response as HttpWebResponse;
if (response != null)
{
throw new WebException(response.StatusDescription, ex);
}
throw ex;
}
catch (Exception exception)
{
throw exception;
}
}
下面,我们来分析上述的现象,发现根本无法找到问题的根本,一头雾水。首先,可以肯定失败的原因是和文件的大小有关的,但是,发生错误的文件大小却是在一个区间段里的,这就无法解释了。然后,我们发现time out的时间都是刚刚超出100m,具体在100-101m之内;这个时间是在需要发送的Request里设的:
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(uploadURL);
....
webRequest.Timeout = 1000;//默认为100m,单位为毫秒
那我们就决定将这个时间设的更长一些,但是,根本没用。其实,我们能基本肯定问题不是在这里,因为在上传90M这么大的文件都能很轻易成功,根据这点我们就有理由怀疑问题不是在这里。但是,这种莫名的问题让我们无法理解,接着,我们就像没头苍蝇一样,将所有可以设置time out的地方都设了,比如IIS,接受上传的WebSite里的config里,结果,大家可想而知。
在代码层面我们已经找不到任何办法了,然后,我们只能怀疑是这台服务器的环境有问题,就把问题抛给了公司的IT。可怜了这些IT,怎么可能找到问题!
后来,美国的同事与微软的工作人员一起联调,终于发现了问题的所在,是我们在发送Request的时候没有精确的指定这个Request的ContentLength,导致Framework底层无法知道你什么时候需要终止这个Request,我们只要在上面的代码中增加这段话:
...
webRequest.ContentType = "application/x-www-form-urlencoded";
webRequest.ContentLength = postedStream.Length;
...
经过测试,发现果然是这个原因。但是,我们就有个问题,微软为什么不在底层处理好这些呢?我们认为微软在底层更能拿到我们的Request的长度,而且更容易包装,更利于使用。
相关文章推荐
- HttpWebRequest提交Form和上传文件的认证问题
- C# HttpWebRequest 上传大文件 超时问题
- java web上传、下载文件源码以及应该注意的问题
- 利用HttpWebRequest上传文件
- C# 使用HttpWebRequest通过PHP接口 上传文件
- 前端文件上传3:使用xmlhttprequest上传图片(web项目)
- 使用WebClient或HttpWebRequest模拟上传文件和数据
- C#在WinForm下使用HttpWebRequest上传文件并显示进度
- 使用HttpWebRequest实现大文件上传(二)
- 将本地文件上传到指定的服务器(HttpWebRequest方法)
- asp.net利用HttpWorkerRequest上传大文件
- 使用WebClient或HttpWebRequest模拟上传文件和数据
- HttpWebRequest上传文件(Excel等)
- c#使用HttpWebRequest上传文件同时携带其他参数
- 解决ajax XMLHttpRequest 跨域上传文件失败问题
- asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端
- 使用HttpWebRequest实现大文件上传(一)
- C# 使用 HttpWebRequest 保持会话上传文件到 HTTP
- C#在WinForm下使用HttpWebRequest上传文件并显示进度
- C#在WinForm下使用HttpWebRequest上传文件并显示进度