C#的HttpClient PUT(C# HttpClient PUT)

2019-08-20 09:23发布

出于某种原因,我下面的代码,用于现在的工作从而引发了异常:

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);
}

任何人发现任何明显?

谢谢

UPDATE

原来获得世博会的家伙来映射他们的存储名称与它的IP,所以我可以回到我原来的代码是最好的解决方案。 我遇到的问题是事做AllowAutoRedirect =假。 发生在HttpResponseMessage RESP =例外等待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();
                    }
                }
            }
        }
    }

感谢谁试图帮助的人们

Answer 1:

原来获得世博会的家伙来映射他们的存储名称与它的IP,所以我可以回到我原来的代码是最好的解决方案。 我遇到的问题是事做AllowAutoRedirect =假。 发生在HttpResponseMessage RESP =例外等待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();
                    }
                }
            }
        }
    }

感谢谁试图帮助的人们



Answer 2:

using (HttpResponseMessage resp = await client.SendAsync(req))

看来,这条线将创建为执行新的上下文,因此一个新的线程上下文,也许你不能这样做,因为你将分享的FileStream的锁。



Answer 3:

它看起来像您所呼叫HttpPut()了,但你还有FileStream打开。 尝试的FileStream处置之前,你递归调用HttpPut()从内部本身。

//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);
                        }

此外,你可能会想处理像HTTP响应任何其他IDisposable的对象,以确保所有的资源被释放你进行深入的堆栈跟踪之前。 这是一个问题递归,当你正使用Using语句,你不会离开他们的范围,使他们没有做他们的工作。



文章来源: C# HttpClient PUT