Поскольку 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)
;
Код: Выделить всё
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();
}
}
Код: Выделить всё
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);
}
Код: Выделить всё
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();
}
Код: Выделить всё
iwr https://localhost:7029/download/container/blob
Подробнее здесь: https://stackoverflow.com/questions/787 ... nse-from-a