Существует ли более быстрый способ потоковой передачи объектов из S3 через Web Api в мой Angular-клиент вместо использования их потока ответов? - PullRequest
0 голосов
/ 06 мая 2019

Для осуществления безопасной загрузки файлов мой клиент Angular запрашивает одноразовый токен, а затем браузер связывает эту конечную точку с токеном, чтобы инициировать загрузку из Asp.Net Web Api.Затем сервер извлекает объект из amazon, я копирую их поток ответов в MemoryStream следующим образом:

using (var client = new AmazonS3Client())
{
                    var request = new GetObjectRequest
                    {
                        BucketName = bucket,
                        Key = key
                    };

                    using (var response = await client.GetObjectAsync(request))
                    using (var responseStream = response.ResponseStream)
                    {
                        streamResponse.ContentLength = response.ContentLength;
                        await responseStream.CopyToAsync(streamResponse.Stream);
                        streamResponse.Stream.Position = 0;
                        return streamResponse;
                    }
}

Как только этот объект-оболочка (streamResponse) возвращается в контроллер, я возвращаю новый HttpResponse сКонтент, настроенный на новый StreamContent, получающий MemoryStream из предыдущего метода:

var httpResponseMessage = new HttpResponseMessage(HttpStatusCode.OK)
                {
                    Content = new StreamContent(_objectFromStorageResponse.StreamResponse.Stream)
                };

                httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment")
                {
                    FileName = _objectFromStorageResponse.FileNm
                };

                httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
                httpResponseMessage.Content.Headers.ContentLength = _objectFromStorageResponse.StreamResponse.ContentLength;

return httpResponseMessage;

Теперь это на самом деле прекрасно работает в том, что касается загрузки пользовательского интерфейса -> Api.Файл потоков в браузер просто отлично.

Однако при работе с большими файлами (> 250 МБ) часть потока копирования становится очень медленной. Таким образом, пользовательский интерфейс должен немного зависать, создавая плохой пользовательский интерфейс, поскольку они ожидаютих загрузка даже началась.Очевидно, я мог бы облегчить проблему пользовательского интерфейса с отображением сообщения или счетчика, позволяющего пользователю знать, что мы обрабатываем загрузку.Но я не могу не думать, что есть лучший способ начать процесс загрузки раньше для конечного пользователя.Я попытался вернуть поток напрямую, а не копировать поток в свой собственный поток, но я думаю, что контроллер все равно сам это делает, потому что кажется, что опыт тот же.

Это единственный способ для меня использовать потоковые объекты S3 из моего веб-API?Есть ли другой способ сделать это?Или это просто так, и мне нужно показать какой-то отзыв пользователю?

1 Ответ

1 голос
/ 06 мая 2019

Как насчет использования комбинации Предопределенный URL и ответа с состоянием HTTP 303/307.

Скажем, например, что вам нужно передать объект x клиенту.

  • Генерирование предварительно назначенного URL-адреса для большого двоичного объекта / объекта в корзине S3 в течение 2 минут (при условии, что на это требуется время, чтобы загрузить контент).
  • отвечает сообщением о статусе HTTP 303 (или 307) и предварительно назначенном URL-адресе.
  • Команда браузера / клиентского приложения / или curl будет следовать перенаправлению HTTP 307 в корзину S3 напрямую с использованием предварительно назначенного URL-адреса.

Даже если какой-то злоумышленник завладеет Предопределенным URL-адресом, он действителен только в течение 2 минут.

Таким образом, ваш код на стороне сервера не должен играть роль посредника в передаче байтов.Этот метод освобождает много памяти и времени на вашем сервере для обслуживания других запросов API.

...