Mam Web API ASP.Net skonfigurowany na mojej stronie internetowej, który jest używany do komunikacji z aplikacją pulpitu WPF. Mam konfigurację działania w interfejsie API, aby odbierać pliki binarne z aplikacji klienckiej. Jednak w niektórych (pozornie przypadkowych) przypadkach, gdy otrzymam wszystkie bajty z żądania, nie wszystkie bajty są odczytywane. Mam nadzieję, że możesz dać mi pomysł, jak to zrobić w sposób, który będzie działał przez cały czas. Oto kod:ASP.Net Web API nie odczytuje wszystkich bajtów z StreamContent
Side Klient:
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 jest enum, które definiuje wynik na serwerze, turnId jest identyfikatorem dla podmiotu plik ten jest dołączony do, i fileStream to rzeczywisty plik FileStream odczytujący liczbę bajtów dysku.
Server Side:
[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;
}
}
Czy był to 32-bitowy system Windows Server 2003 lub Windows XP? Zachowujemy się tak samo z StreamContent, ale podczas przesyłania strumieniowego odpowiedzi z usługi Web API systemu Windows Server 2003. Nie ma repro w 2008 roku. Odkryliśmy również, że jest to tylko repros z FileStream. Konwersja strumienia FileStream do MemoryStream omija problem (oczywiście kosztem pamięci). Odkryliśmy, że kiedy strumień odpowiedzi kończy się wcześniej, zawsze jest na granicy 4096 bajtów i osiąga limit około 3,5 MB. –