76086


ASP.NET .NET Frameworkを利用してWebAPIを開発しています。  
クラウドストレージ(AWSのS3)にファイルを配置し、それをダウンロードさせるWebAPIを作りたいと考えています。  
以下のような形で作成し、ダウンロードできることは確認しました。

しかしこのやり方だとWebAPIのサーバーにファイルができるまで呼び出し元が待たされることになります。  
S3から一時ファイルを作らずに一気にダウンロードさせる方法はないでしょうか？

[code]

        [Route("download/s3")]
        [HttpGet]
        public IHttpActionResult GetS3Data(string key)
        {
            // データベースにアクセスし、keyからバケット名、ダウンロード元パス、ダウンロード先パスを取得
            IAmazonS3 client = new AmazonS3Client(RegionEndpoint.USEast2);
    
            GetBucketLocationRequest request1 = new GetBucketLocationRequest
            {
                BucketName = バケット名
            };
    
            // リージョン取得
            string location = client.GetBucketLocation(request1).Location.Value;
            client = new AmazonS3Client(RegionEndpoint.GetBySystemName(location));
                
            TransferUtilityDownloadRequest request2 = new TransferUtilityDownloadRequest
            {
                BucketName = バケット名,
                Key = ダウンロード元パス,
                FilePath = サーバー内のダウンロード先パス
            };
    
            var fileTransferUtility = new TransferUtility(client);
            fileTransferUtility.Download(request2);
    
            //ファイルを開く
            using (FileStream fs = new FileStream(dlDestPath, FileMode.Open, FileAccess.Read))
            {
                //ファイルを読み込むバイト型配列を作成する
                byte[] bs = new byte[fs.Length];
                //ファイルの内容をすべて読み込む
                fs.Read(bs, 0, bs.Length);
                fs.Close();
                // 一時ファイル削除
                File.Delete(dlDestPath);
                return Ok(Convert.ToBase64String(bs));
            }
        }
    
[/code]


CC BY-SA 4.0
2021-05-26T08:36:23.150
76081
2021-05-27T11:38:59.373
2021-05-26T11:32:31.797
3060
23880
question
c# asp.net amazon-s3 webapi
Amazon S3 からファイルを直接ダウンロードするようなWebAPIはどのように作れば良いか？


AWS SDK for
.NETの[`Amazon.S3.Transfer.TransferUtility`クラス](https://docs.aws.amazon.com/sdkfornet/v3/apidocs/index.html?page=S3/TTransferUtility.html&tocid=Amazon_S3_Transfer_TransferUtility)には`Download`メソッドのほかに`OpenStream`メソッドが用意されています。こちらを使用して得られたstreamをWebAPIのレスポンスに渡せば、ASP.NET側がストリーム間コピーをしてくれるはずです。

* * *

全く別のアプローチで、AWS S3には[presigned
URL](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ShareObjectPreSignedURL.html)という機能があります。こちらを使用するとダウンロード用URLを生成することができるので、WebAPIのレスポンスとしてそのアドレスにリダイレクトしてやると、サーバーを介さずクライアントが直接S3からダウンロードするようになります。


CC BY-SA 4.0
2021-05-26T11:16:49.980
76086
2021-05-26T11:16:49.980
4236
76081
answer


OpenStreamメソッドを使ってAPI側を実現できました。

[code]

    using(var transferUtility = new TransferUtility(client))
    {
        var stream = transferUtility.OpenStream(bucketName, filePath);
    
        var result = new HttpResponseMessage(HttpStatusCode.OK)
        {
            Content = new StreamContent(stream)
        };
        result.Content.Headers.ContentDisposition =
            new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
            {
                FileName = "testfile.zip"
            };
        result.Content.Headers.ContentType =
            new System.Net.Http.Headers.MediaTypeHeaderValue("application/octet-stream");
    
        var response = ResponseMessage(result);
    
        return response;
    }
    
[/code]


CC BY-SA 4.0
2021-05-27T10:21:10.587
76115
2021-05-27T11:38:59.373
2021-05-27T11:38:59.373
3060
23880
76081
answer