繁体   English   中英

是否有更快的方法通过Web Api将对象从S3流传输到我的Angular客户端,而不使用它们的响应流?

[英]Is there a faster way to stream objects from S3 over Web Api to my Angular client instead of using their response stream?

为了实现安全文件下载,我的Angular客户端请求一个一次性令牌,然后浏览器使用该令牌命中该端点,以启动从Asp.Net Web Api的下载。 然后服务器从亚马逊检索对象,我将其响应流复制到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)返回到控制器,我就将Content设置为新的StreamContent的新HttpResponse返回,从先前的方法接收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;

现在,就UI-> Api下载而言,这实际上非常有效。 该文件流到浏览器就好了。

但是,对于大文件(> 250MB),复制流部分变得非常慢。 因此,UI必须挂起一会儿,在等待下载甚至开始时会产生不良的用户体验。 显然,我可以通过显示消息或微调框来缓解UI问题,让用户知道我们正在处理下载。 但是我不禁想到有一种更好的方法可以让最终用户更快地开始下载过程。 我尝试过直接返回流,而不是将流复制到自己的流中,但是我认为控制器还是会这样做,因为体验似乎是相同的。

这是我利用Web API中的流S3对象的唯一方法吗? 还有另一种方式吗? 还是这只是它的工作方式,我需要向用户显示一些反馈?

如何使用预签名URL组合并以HTTP 303/307状态进行响应。

举例来说,您需要将对象x共享给客户端。

  • 生成一个指向S3存储桶中的Blob /对象的Presigned URL,持续2分钟(假设多数民众赞成在多长时间内下载内容)。
  • 以HTTP 303(或307)状态和Presigned URL响应。
  • 浏览器/客户端应用程序/或curl命令将使用预签名URL直接遵循HTTP 307重定向到S3存储桶。

即使某些恶意播放器掌握了Presigned URL,它也仅在2分钟内有效。

这样,您的服务器端代码不必在传输字节时扮演中间人的角色。 此方法释放了服务器上的大量内存和时间来处理其他API请求。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM