我想在上传大文件时,我遗漏了HttpWebRequest如何通过流媒体工作。 基本上,我发现在向服务器发送大文件时会收到超时异常,因此建议通过异步执行此操作并自行处理超时。
问题是,在调试之后,我发现了“GetRequestStreamAsync”方法,并且写入它在服务器端什么都不做,只在执行GetResponseAsync时调用服务器
所以我的问题是:
- 标记为// 1的代码 - 它将文件写入请求流,但我没有看到内存正在增加,或者服务器甚至没有得到任何请求 - 流式传输到哪里?
这基本上就是我的代码:
HttpWebRequest request = RESTUtils.InitializeRequest(...);
request.AllowWriteStreamBuffering = false;
request.ContentLength = i_InputStream.Length;
request.Timeout = 5000;
using (Stream requestStream = request.GetRequestStreamWithTimeout())
{
if (requestStream != null) //1
{
// We will write the stream to the request
byte[] buffer = new byte[UPLOAD_FILE_BUFFER_SIZE];
int read = i_InputStream.Read(buffer, 0, buffer.Length);
while (read > 0)
{
requestStream.Write(buffer, 0, read);
read = i_InputStream.Read(buffer, 0, buffer.Length);
}
}
}
using (var response = request.GetResponseWithTimeout(-1))
{
using (var responseStream = response.GetResponseStream())
{
}
}
public static class WebRequestExtensions
{
public static Stream GetRequestStreamWithTimeout(
this WebRequest request,
int? millisecondsTimeout = null)
{
return AsyncToSyncWithTimeout(
request.BeginGetRequestStream,
request.EndGetRequestStream,
millisecondsTimeout ?? request.Timeout);
}
public static WebResponse GetResponseWithTimeout(
this HttpWebRequest request,
int? millisecondsTimeout = null)
{
return AsyncToSyncWithTimeout(
request.BeginGetResponse,
request.EndGetResponse,
millisecondsTimeout ?? request.Timeout);
}
private static T AsyncToSyncWithTimeout<T>(
Func<AsyncCallback, object, IAsyncResult> begin,
Func<IAsyncResult, T> end,
int millisecondsTimeout)
{
var iar = begin(null, null);
if (!iar.AsyncWaitHandle.WaitOne(millisecondsTimeout))
{
var ex = new TimeoutException();
throw new WebException(ex.Message, ex, WebExceptionStatus.Timeout, null);
}
return end(iar);
}
}
谢谢!
==编辑9/9/15 ==
甚至更奇怪的事情发生了,我在GetResponseAsync之后立即附加断点,然后我看到服务器接收到呼叫。 之后,我正在关闭客户端的流程 - &gt;服务器正在成功上传文件。
如果我做“中止”,也会发生这种情况。 有谁知道为什么?答案 0 :(得分:0)
不应使用旧式的开始/结束异步模式,而应考虑切换到async/await,这将大大简化您的代码。
然后,您可以根据请求将Timeout
属性设置为较大的值以适应您的等待时间;然后你可以这样做,而不是使用基于回调的异步代码:
var request = SomeMethodToCreateRequest();
request.Timeout = int.MaxValue; // (don't do this)
var response = await request.GetResponse();
应该在内部遵守超时,您可以简化代码。