Тайм-ауты не поддерживаются в этом потоке. Невозможно получить ответ потока от API и сохранить файл на локальный диск в C#

Место общения программистов C#
Anonymous
Тайм-ауты не поддерживаются в этом потоке. Невозможно получить ответ потока от API и сохранить файл на локальный диск в

Сообщение Anonymous »

В моем приложении Blazor WASM есть функция загрузки файлов. При вызове моего API для загрузки определенного файла API обращается к хранилищу BLOB-объектов, где сохраняется файл, и возвращает его клиенту.
Поскольку BLOB-объекты могут быть больше, я хочу свести их к минимуму. потребление памяти API, поэтому я хочу получить большой двоичный объект в виде потока и передать его клиенту.
Я использую Azure Storage SDK для взаимодействия с хранилищем больших двоичных объектов. Мой API возвращает эту ошибку

Код: Выделить всё

System.InvalidOperationException: Timeouts are not supported on this stream.
at System.IO.Stream.get_ReadTimeout()
at System.Text.Json.Serialization.Metadata.JsonPropertyInfo`1.GetMemberAndWriteJson(Object obj, WriteStack& state, Utf8JsonWriter writer)
at System.Text.Json.Serialization.Converters.ObjectDefaultConverter`1.OnTryWrite(Utf8JsonWriter writer, T value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.TryWrite(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.JsonConverter`1.WriteCore(Utf8JsonWriter writer, T& value, JsonSerializerOptions options, WriteStack& state)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(Stream utf8Json, T rootValue, CancellationToken cancellationToken, Object rootValueBoxed)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(Stream utf8Json, T rootValue, CancellationToken cancellationToken, Object rootValueBoxed)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(Stream utf8Json, T rootValue, CancellationToken cancellationToken, Object rootValueBoxed)
at System.Text.Json.Serialization.Metadata.JsonTypeInfo`1.SerializeAsync(Stream utf8Json, T rootValue, CancellationToken cancellationToken, Object rootValueBoxed)
at Microsoft.AspNetCore.Http.HttpResponseJsonExtensions.WriteAsJsonAsyncSlow[TValue](Stream body, TValue value, JsonSerializerOptions options, CancellationToken cancellationToken)
at Microsoft.AspNetCore.Http.RequestDelegateFactory.ExecuteTaskResult[T](Task`1 task, HttpContext httpContext)
at Microsoft.AspNetCore.Authorization.AuthorizationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Authentication.AuthenticationMiddleware.Invoke(HttpContext context)
at Microsoft.AspNetCore.Diagnostics.DeveloperExceptionPageMiddlewareImpl.Invoke(HttpContext context)
Вот код
минимальная конечная точка API

Код: Выделить всё

app.MapGet("/download/{container}/{blob}", async (HttpContext ctx, [FromServices] IBlobService blobSvc, string container, string blob) =>
{
var b = await blobSvc.GetBlobStream(container, blob);
return Results.Ok(b);
})
.RequireAuthorization(AuthzPolicy.Policy)
;
служба BLOB-объектов/с использованием Azure Storage SDK

Код: Выделить всё

public class BlobService : IBlobService
{
readonly BlobServiceClient _svcClient;
BlobContainerClient _getContainerClient(string containerName) => _svcClient.GetBlobContainerClient(containerName);
BlobClient _getBlobClient(string containerName, string file) => _getContainerClient(containerName).GetBlobClient(file);
public BlobService(string blobEndpoint)
{
var cred = new DefaultAzureCredential();
_svcClient = new (new Uri (blobEndpoint), cred);
}

public async Task  GetBlobStream(string containerName, string file)
{
var blobClient = _getBlobClient(containerName, file);
return await blobClient.OpenReadAsync();
}
}
Код клиента Blazor WASM для загрузки

Код: Выделить всё

async Task _download(string container, string blob)
{
HttpClient http = httpFactory.CreateClient(HttpClientName.REST);
HttpResponseMessage resp = await http.GetAsync($"/download/{container}/{blob}");
if (!resp.IsSuccessStatusCode)
{
throw new ApplicationException(JsonSerializer.Serialize(resp.ReasonPhrase));
}

// JS interop due to WASM
using var streamRef = new Microsoft.JSInterop.DotNetStreamReference(await resp.Content.ReadAsStreamAsync());
await _js.InvokeVoidAsync("download", blob, streamRef);
}
Взаимодействие с Javascript

Код: Выделить всё

async function download(fileName, fileStream) {
const arrayBuffer = await fileStream.arrayBuffer();
const blob = new Blob([arrayBuffer]);
const url = URL.createObjectURL(blob);

triggerDownload(fileName, url);
URL.revokeObjectURL(url);
}

function triggerDownload(fielName, url) {
const anchorElement = document.createElement("a");
anchorElement.href = url;
anchorElement.download = fielName;
anchorElement.click();
anchorElement.remove();
}
Вы видите в этом что-то не так? Я получаю ту же ошибку, когда просто использую Powershell для запроса загрузки с помощью следующего, что заставляет меня думать, что это не связано с клиентским кодом, а скорее ошибка находится на уровне API.

Код: Выделить всё

iwr https://localhost:7029/download/container/blob
Любая помощь в этом вопросе будет очень признательна.

Подробнее здесь: https://stackoverflow.com/questions/787 ... nse-from-a

Вернуться в «C#»