我在我的网站上设置了ASP.Net Web API,用于与
WPF桌面应用程序通信.我在API上有一个动作设置来从客户端应用程序接收二进制文件.但是在某些(看似随机的)情况下,当我从请求中获取所有字节时,不会读取所有字节.希望你可以让我知道如何以一种始终有效的方式做到这一点.这是代码:
客户端:
public static SubmitTurnResult SubmitTurn(int turnId,Stream fileStream) { HttpClient client = CreateHttpClient(); HttpContent content = new StreamContent(fileStream); content.Headers.Contentdisposition = new ContentdispositionHeaderValue("attachment"); content.Headers.Contentdisposition.FileName = "new-turn.Civ5Save"; content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream"); content.Headers.ContentLength = fileStream.Length; HttpResponseMessage response = client.PostAsync( string.Format("SubmitTurn?authKey={0}&turnId={1}",LocalSettings.Instance.AuthenticationKey,turnId ),content ).Result; response.EnsureSuccessstatusCode(); return response.Content.ReadAsAsync<SubmitTurnResult>().Result; }
SubmitTurnResult是一个枚举,用于定义服务器上的结果,turnId是此文件附加到的实体的ID,fileStream是读取磁盘字节的实际FileStream.
服务器端:
[HttpGet,HttpPost] public SubmitTurnResult SubmitTurn(string authKey,int turnId) { try { bool worked = false; int gameId = 0; using (GmrEntities gmrDb = new GmrEntities()) { var player = gmrDb.Users.FirstOrDefault(u => u.AuthKey == authKey); if (player != null) { var turn = player.Turns.FirstOrDefault(t => t.TurnID == turnId); if (turn != null) { byte[] saveFileBytes = null; using (MemoryStream tempStream = new MemoryStream()) { var task = this.Request.Content.copyToAsync(tempStream); task.Wait(); saveFileBytes = tempStream.ToArray(); tempStream.Close(); } if (saveFileBytes.Length != this.Request.Content.Headers.ContentLength.Value) { throw new Exception(string.Format("Byte array length ({0}) not equal to HTTP content-length header ({1}). This is not good!",saveFileBytes.Length,this.Request.Content.Headers.ContentLength.Value)); } worked = GameManager.SubmitTurn(turn,saveFileBytes,gmrDb); if (worked) { gameId = turn.Game.GameID; gmrDb.SaveChanges(); } } } } return SubmitTurnResult.OK; } catch (Exception exc) { DebugLogger.WriteExceptionWithComments(exc,string.Format("Diplomacy: Sumbitting turn for turnId: {0}",turnId)); return SubmitTurnResult.UnexpectedError; } }
解决方法
正如我之前的评论中所述,我们遇到了与StreamContent相同的行为,但是在从Windows Server 2003 Web API服务流式传输响应时.它不会在2008年重新生成.实际上,如果我使用少量RAM(712 MB)配置VM,它也会在Windows Server 2008上进行重新编译,但是如果使用4 GB RAM则不会重新编译.此外,我们发现这只有一个带有FileStream的repros.将FileStream转换为MemoryStream会绕过问题(当然是以内存为代价).我们发现当响应流提前终止时,它总是在4096字节的边界上,并且它达到大约3.5MB的上限.
public static SubmitTurnResult SubmitTurn(int turnId,Stream fileStream) { HttpClient client = CreateHttpClient(); var memoryStream = new MemoryStream((int)fileStream.Length); fileStream.copyTo(memoryStream); fileStream.Close(); memoryStream.Seek(0,SeekOrigin.Begin); HttpContent content = new StreamContent(memoryStream);
如果需要,只有在Stream是FileStream时才可以有条件地执行MemoryStream复制.
原文地址:https://www.jb51.cc/csharp/91737.html
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。