您好我想将一些动态生成的内容上传到我的网络API。 在客户端我使用HttpWebRequest。数据应该上传同步,我想写入流AFTER(!)我执行了HTTP请求。
(从服务器到客户端它运行正常,但是从客户端到服务器我得到一些例外)。
客户端实现如下:
HttpWebRequest httpWebRequest = HttpWebRequest.Create(myUrl) as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.Headers["Authorization"] = "Basic " + ... ;
httpWebRequest.PreAuthenticate = true;
httpWebRequest.SendChunked = true;
//httpWebRequest.AllowWriteStreamBuffering = false; //does not help...
httpWebRequest.ContentType = "application/octet-stream";
Stream st = httpWebRequest.GetRequestStream();
Task<WebResponse> response = httpWebRequest.GetResponseAsync();
// NOW: Write after GetResponse()
var b = Encoding.UTF8.GetBytes("Test1");
st.Write(b, 0, b.Length);
b = Encoding.UTF8.GetBytes("Test2");
st.Write(b, 0, b.Length);
b = Encoding.UTF8.GetBytes("Test3");
st.Write(b, 0, b.Length);
st.Close();
var x = response.Result;
Stream resultStream = x.GetResponseStream();
//do some output...
我在stream.write()上得到异常(NotSupportedException:流不支持并发IO读取或写入操作。)。
为什么我会在这里遇到例外情况。有时第一次写入worke而后期写入会抛出异常。 在开始时,stream.CanWrite属性为true,但在第一次或第二次或第四次写入后,它变为false ...然后在下次写入时抛出异常。
编辑:更改AllowWriteStreamBuffering没有帮助
附录 我发现了我的问题。此问题是由我的代码顺序引起的。 我必须按此顺序调用它:
我认为“GetResponseAsync”会触发客户端发送请求(目前只有标头)。 但是没有必要,因为在我将第一个比特写入流后,请求已经发送。
我的问题的第二个原因:提琴手。 (Fiddler目前仅支持响应流而不是请求)
答案 0 :(得分:9)
我发现了我的问题。
我的代码顺序导致了问题。
解决方案是按此顺序调用它:
我的理解是&#34; GetResponseAsync&#34;触发客户端发送请求(现在只是头文件),但我发现它是一个不必要的步骤,因为在将前几位写入流之后已经发送了请求。
我遇到问题的第二个原因是Fiddler,但Fiddler只支持回复流,而不支持请求。
代码实现了引用,&#39; HttpWebRequest&#39;类:
HttpWebRequest httpWebRequest = HttpWebRequest.Create("http://xxx") as HttpWebRequest;
httpWebRequest.Method = "POST";
httpWebRequest.Headers["Authorization"] = "Basic " + Convert.ToBase64String(Encoding.ASCII.GetBytes("user:pw"));
httpWebRequest.PreAuthenticate = true;
httpWebRequest.SendChunked = true;
httpWebRequest.AllowWriteStreamBuffering = false;
httpWebRequest.AllowReadStreamBuffering = false;
httpWebRequest.ContentType = "application/octet-stream";
Stream st = httpWebRequest.GetRequestStream();
Console.WriteLine("Go");
try
{
st.Write(buffer, 0, buffer.Length); //with the first write, the request will be send.
st.Write(buffer, 0, buffer.Length);
st.Write(buffer, 0, buffer.Length);
for (int i = 1; i <= 10; i++)
{
st.Write(buffer, 0, buffer.Length); //still writing while I can read on the stream at my ASP.NET web api
}
}
catch (WebException ex)
{
var y = ex.Response;
}
finally
{
st.Close();
}
// Now we can read the response from the server in chunks
Task<WebResponse> response = httpWebRequest.GetResponseAsync();
Stream resultStream = response.Result.GetResponseStream();
byte[] data = new byte[1028];
int bytesRead;
while ((bytesRead = resultStream.Read(data, 0, data.Length)) > 0)
{
string output = System.Text.Encoding.UTF8.GetString(data, 0, bytesRead);
Console.WriteLine(output);
}
代码实现了引用,&#39; HttpClient&#39;类:
HttpClientHandler ch = new HttpClientHandler();
HttpClient c = new HttpClient(ch);
c.DefaultRequestHeaders.TransferEncodingChunked = true;
c.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Basic", Convert.ToBase64String(Encoding.ASCII.GetBytes("user:pw")));
Stream stream = new MemoryStream();
AsyncStream asyncStream = new AsyncStream(); // Custom implementation of the PushStreamContent with the method, "WriteToStream()".
PushStreamContent streamContent = new PushStreamContent(asyncStream.WriteToStream);
HttpRequestMessage requestMessage = new HttpRequestMessage(new HttpMethod("POST"), "http://XXX") { Content = streamContent };
requestMessage.Headers.TransferEncodingChunked = true;
HttpResponseMessage response = await c.SendAsync(requestMessage, HttpCompletionOption.ResponseHeadersRead);
// The request has been sent, since the first write in the "WriteToStream()" method.
response.EnsureSuccessStatusCode();
Task<Stream> result = response.Content.ReadAsStreamAsync();
byte[] data = new byte[1028];
int bytesRead;
while ((bytesRead = await result.Result.ReadAsync(data, 0, data.Length)) > 0)
{
string output = System.Text.Encoding.UTF8.GetString(data, 0, bytesRead);
Console.WriteLine(output);
}
Console.ReadKey();
答案 1 :(得分:0)
您正在同时在多个线程上使用HttpWebRequest
的对象。 response
是与您的写入同时运行的任务。这显然是线程不安全的。
另外,我不知道你想要达到的目标。 HTTP具有请求然后响应模型。在接收整个请求之前,服务器不能(通常)发送单个响应字节。从理论上讲,这是可能的。但这很不寻常,可能不受.NET BCL的支持。这只能由您的(非常不寻常的)自定义HTTP服务器支持。