Описание : я изменяю службу ASP.NET Core Web API (размещенную в службе Windows), которая поддерживает возобновляемую загрузку файлов. Это работает нормально и возобновляет загрузку файлов при многих условиях отказа, за исключением одного, описанного ниже.
Проблема : Когда служба находится на другом компьютере, а клиент на моем, и я отсоединяю кабель на своем компьютере, клиент обнаруживает отсутствие сети, пока служба зависает на fileSection.FileStream. Читать(). Иногда служба обнаруживает сбой за 8 минут, иногда за 20, иногда никогда.
Я также заметил, что после того, как я отсоединяю кабель и останавливаю клиента, служба застревает в функции Read () и размер файла составляет x КБ, но когда служба наконец обнаруживает исключение через некоторое время, она записывает дополнительные 4 КБ в файл. Это странно, потому что я отключил буферизацию и размер буфера составляет 2 КБ.
Вопрос : Как правильно определить отсутствие сети в службе, или правильно отключить время ожидания, или отменить запрос
Сервисный код :
public static async Task<List<(Guid, string)>> StreamFileAsync(
this HttpRequest request, DeviceId deviceId, FileTransferInfo transferInfo)
{
var boundary = GetBoundary(MediaTypeHeaderValue.Parse(request.ContentType), DefaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, request.Body);
var section = await reader.ReadNextSectionAsync(_cancellationToken);
if (section != null)
{
var fileSection = section.AsFileSection();
var targetPath = transferInfo.FileTempPath;
try
{
using (var outfile = new FileStream(transferInfo.FileTempPath, FileMode.Append, FileAccess.Write, FileShare.None))
{
var buffer = new byte[DefaultCopyBufferSize];
int read;
while ((read = fileSection.FileStream.Read(buffer, 0, buffer.Length)) > 0) // HANGS HERE
{
outfile.Write(buffer, 0, read);
transferInfo.BytesSaved = read + transferInfo.BytesSaved;
}
}
}
catch (Exception e)
{
...
}
}
}
Код клиента :
var request = CreateRequest(fileTransferId, boundary, header, footer, filePath, offset, headers, null);
using (Stream formDataStream = request.GetRequestStream())
{
formDataStream.ReadTimeout = 60000;
formDataStream.Write(Encoding.UTF8.GetBytes(header), 0, header.Length);
byte[] buffer = new byte[2048];
using (FileStream fs = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read))
{
fs.Seek(offset, SeekOrigin.Begin);
for (int i = 0; i < fs.Length - offset;)
{
int k = await fs.ReadAsync(buffer, 0, buffer.Length);
if (k > 0)
{
await Task.Delay(100);
await formDataStream.WriteAsync(buffer, 0, k);
}
i = i + k;
}
}
formDataStream.Write(footer, 0, footer.Length);
}
var uploadingResult = request.GetResponse() as HttpWebResponse;
private static HttpWebRequest CreateRequest(
Guid fileTransferId,
string boundary,
string header,
byte[] footer,
string filePath,
long offset,
NameValueCollection headers,
Dictionary<string, string> postParameters)
{
var url = $"{_BaseAddress}v1/ResumableUpload?fileTransferId={fileTransferId}";
HttpWebRequest request = (HttpWebRequest) WebRequest.Create(url);
request.Method = "POST";
request.ContentType = "multipart/form-data; boundary=\"" + boundary + "\"";
request.UserAgent = "Agent 1.0";
request.Headers.Add(headers); // custom headers
request.Timeout = 120000;
request.KeepAlive = true;
request.AllowReadStreamBuffering = false;
request.ReadWriteTimeout = 120000;
request.AllowWriteStreamBuffering = false;
request.ContentLength = CalculateContentLength(filePath, offset, header, footer, postParameters, boundary);
return request;
}
Что я пробовал :
Я добавил их в конфигурационные файлы:
Попытка установить тайм-аут на сервере
var host = new WebHostBuilder (). UseKestrel (o => {o.Limits.KeepAliveTimeout = TimeSpan.FromMinutes (2);})
Используется асинхронное и не асинхронное чтение ()
Пробовал с сохранением в живых и без
Попытка прервать запрос при восстановлении сети: request? .Abort ();
Попытка установить formDataStream.ReadTimeout = 60000;