gpt4 book ai didi

c# - ASP.Net Web API 不会从 StreamContent 中读取所有字节

转载 作者:太空狗 更新时间:2023-10-29 21:09:42 26 4
gpt4 key购买 nike

我在我的网站上设置了一个 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。将 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/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com