我的网站上设置了一个ASP.Net Web API,用于与WPF table 面应用程序进行通信。我在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年复制。实际上,如果我将VM配置为具有少量RAM(712 MB),但具有4 GB RAM,则它也不会在Windows Server 2008上复制。另外,我们发现这仅在FileStream中再现。将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复制。
关于c# - ASP.Net Web API不会从StreamContent读取所有字节,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/13533672/