出于某种原因,我现在使用的下面的代码因此引发了异常:
public static async Task<string> HttpPut(string inUrl, string inFilePath)
{
using (var handler = new HttpClientHandler
{
AllowAutoRedirect = false
})
{
using (var client = new HttpClient(handler))
{
//var content = new StreamContent(new FileStream(inFilePath, FileMode.Open, FileAccess.Read, FileShare.Read, bufferSize: 4096, useAsync: true));
using (var content = new StreamContent(new FileStream(inFilePath, FileMode.Open)))
{
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/octet-stream");
using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl))
{
string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password);
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization", "Basic " + authInfo);
req.Headers.Remove("Expect");
req.Headers.Add("Expect", "");
//req.Headers.TransferEncodingChunked = true;
req.Content = content;
// Ignore Certificate validation failures (aka untrusted certificate + certificate chains)
ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
using (HttpResponseMessage resp = await client.SendAsync(req))
{
//This part is specific to the setup on an Expo we're at...
if (resp.StatusCode == HttpStatusCode.Redirect || resp.StatusCode == HttpStatusCode.TemporaryRedirect)
{
string redirectUrl = resp.Headers.Location.ToString();
if (redirectUrl.Contains("vme-store"))
{
redirectUrl = redirectUrl.Replace("vme-store", "10.230.0.11");
}
return await HttpPut(redirectUrl, inFilePath);
}
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
}
}
}
}
}
我得到的例外是:
System.NotSupportedException was unhandled
HResult=-2146233067
Message=The stream does not support concurrent IO read or write operations.
Source=System
StackTrace:
at System.Net.ConnectStream.InternalWrite(Boolean async, Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.ConnectStream.BeginWrite(Byte[] buffer, Int32 offset, Int32 size, AsyncCallback callback, Object state)
at System.Net.Http.StreamToStreamCopy.BufferReadCallback(IAsyncResult ar)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at VizWolfInnerServer.Tools.HttpConnector.<HttpPut>d__39.MoveNext() in c:\Users\christer\Documents\Visual Studio 2012\Projects\VizWolfNew\VizWolfInnerServer\Tools\HttpConnector.cs:line 202
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()
at VizWolfInnerServer.Tools.VizAPIConnector.<VmeUploadMedia>d__0.MoveNext() in c:\Users\christer\Documents\Visual Studio 2012\Projects\VizWolfNew\VizWolfInnerServer\Tools\VizAPIConnector.cs:line 187
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.CompilerServices.AsyncMethodBuilderCore.<ThrowAsync>b__1(Object state)
at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
at System.Threading.QueueUserWorkItemCallback.System.Threading.IThreadPoolWorkItem.ExecuteWorkItem()
at System.Threading.ThreadPoolWorkQueue.Dispatch()
InnerException:
我很难找到HttpClient的正确文档和示例,我正在努力弄清楚为什么这突然不起作用(与StringContent完全相似的方法而不是StreamContent完美地工作)...
它最初是从它自己的线程中调用的,然后像这样:
public static async void VmeUploadMedia(string inUploadLink, string inFilePath)
{
string result = await HttpConnector.HttpPut(inUploadLink, inFilePath);
}
有人发现任何明显的事情吗?
由于
更新
结果让那些世界各地的人用它的IP映射他们的存储名称,所以我可以回到原来的代码是最好的解决方案。我遇到的问题与AllowAutoRedirect = false有关。在HttpResponseMessage resp = await client.SendAsync(req)上发生异常,即使实际上没有重定向。我有点迷失为什么它甚至发生了,但使用这个代码现在一切正常:
public static async Task<string> HttpPut(string inUrl, string inFilePath)
{
using (var client = new HttpClient())
{
using (var content = new StreamContent(File.OpenRead(inFilePath)))
{
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/octet-stream");
using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl))
{
string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password);
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization", "Basic " + authInfo);
req.Headers.Remove("Expect");
req.Headers.Add("Expect", "");
req.Content = content;
// Ignore Certificate validation failures (aka untrusted certificate + certificate chains)
ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
using (HttpResponseMessage resp = await client.SendAsync(req))
{
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
}
}
}
}
感谢那些试图帮助的人
答案 0 :(得分:8)
结果让那些世界各地的人用它的IP映射他们的存储名称,所以我可以回到原来的代码是最好的解决方案。我遇到的问题与AllowAutoRedirect = false有关。在HttpResponseMessage resp = await client.SendAsync(req)上发生异常,即使实际上没有重定向。我有点迷失为什么它甚至发生了,但使用这个代码现在一切正常:
public static async Task<string> HttpPut(string inUrl, string inFilePath)
{
using (var client = new HttpClient())
{
using (var content = new StreamContent(File.OpenRead(inFilePath)))
{
content.Headers.Remove("Content-Type");
content.Headers.Add("Content-Type", "application/octet-stream");
using (var req = new HttpRequestMessage(HttpMethod.Put, inUrl))
{
string authInfo = String.Format("{0}:{1}", Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").UserName, Program.Config.MediaStorageList.Find(o => o.Name == "Viz Media Engine Test").Password);
authInfo = Convert.ToBase64String(Encoding.Default.GetBytes(authInfo));
req.Headers.Add("Authorization", "Basic " + authInfo);
req.Headers.Remove("Expect");
req.Headers.Add("Expect", "");
req.Content = content;
// Ignore Certificate validation failures (aka untrusted certificate + certificate chains)
ServicePointManager.ServerCertificateValidationCallback = ((sender, certificate, chain, sslPolicyErrors) => true);
using (HttpResponseMessage resp = await client.SendAsync(req))
{
resp.EnsureSuccessStatusCode();
return await resp.Content.ReadAsStringAsync();
}
}
}
}
}
感谢那些试图帮助的人
答案 1 :(得分:1)
using (HttpResponseMessage resp = await client.SendAsync(req))
似乎这一行会为该执行创建一个新的上下文,因此一个新的线程上下文,也许你不能这样做,因为你将共享FileStream的锁。
答案 2 :(得分:0)
您似乎再次致电HttpPut()
,但仍然打开了FileStream
。在从内部递归调用HttpPut()
之前尝试处理FileStream。
//This part is specific to the setup on an Expo we're at...
if (resp.StatusCode == HttpStatusCode.Redirect || resp.StatusCode == HttpStatusCode.TemporaryRedirect)
{
string redirectUrl = resp.Headers.Location.ToString();
if (redirectUrl.Contains("vme-store"))
{
redirectUrl = redirectUrl.Replace("vme-store", "10.230.0.11");
}
content.Dispose();
return await HttpPut(redirectUrl, inFilePath);
}
此外,您可能希望处理任何其他IDisposable对象(如http响应),以确保在深入到堆栈跟踪之前释放所有资源。这是递归的一个问题,当你使用Using
语句时,你不会离开他们的范围,所以他们没有做好自己的工作。