簡體   English   中英

C#MVC從S3 Async下載大文件

[英]C# MVC Download Big File from S3 Async

我必須從aws S3 async下載一個文件。 我有一個錨標簽,點擊它時,一個方法將在控制器中命中下載。 該文件應該在瀏覽器底部開始下載,就像其他文件下載一樣。

在視圖中

<a href="/controller/action?parameter">Click here</a>

在控制器中

public void action()
{
     try
     {
           AmazonS3Client client = new AmazonS3Client(accessKeyID, secretAccessKey);
           GetObjectRequest req = new GetObjectRequest();
           req.Key = originalName;
           req.BucketName = ConfigurationManager.AppSettings["bucketName"].ToString() + DownloadPath;
           FileInfo fi = new FileInfo(originalName);
           string ext = fi.Extension.ToLower();
           string mimeType = ReturnmimeType(ext);
           var res = client.GetObject(req);
           Stream responseStream = res.ResponseStream;
           Stream response = responseStream;
           return File(response, mimeType, downLoadName);
     }
     catch (Exception)
     {
           failure = "File download failed. Please try after some time.";   
     }              
}

上述功能使瀏覽器加載,直到文件完全下載。 然后只在底部顯示該文件。 我看不到mb是如何下載的。
提前致謝。

您必須將ContentLength發送到客戶端才能顯示進度。 瀏覽器沒有關於它將接收多少數據的信息。

如果查看File方法使用的FileStreamResult類的源代碼,它不會通知客戶端有關“Content-Length”的信息。 https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/FileStreamResult.cs

替換這個,

return File(response, mimeType, downLoadName);

return new FileStreamResultEx(response, res.ContentLength, mimeType, downloadName);


public class FileStreamResultEx : ActionResult{

     public FileStreamResultEx(
        Stream stream, 
        long contentLength,         
        string mimeType,
        string fileName){
        this.stream = stream;
        this.mimeType = mimeType;
        this.fileName = fileName;
        this.contentLength = contentLength;
     }


     public override void ExecuteResult(
         ControllerContext context)
     {
         var response = context.HttpContext.Response; 
         response.BufferOutput = false;
         response.Headers.Add("Content-Type", mimeType);
         response.Headers.Add("Content-Length", contentLength.ToString());
         response.Headers.Add("Content-Disposition","attachment; filename=" + fileName);

         using(stream) { 
             stream.CopyTo(response.OutputStream);
         }
     }

}

替代

通常,從服務器下載和傳送S3文件是一種不好的做法。 您的主機帳戶將收取兩倍的帶寬費用。 相反,您可以使用簽名URL來傳遞非公共S3對象,只需幾秒鍾的時間。 您只需使用Pre-Signed-URL即可

 public ActionResult Action(){
     try{
         using(AmazonS3Client client = 
              new AmazonS3Client(accessKeyID, secretAccessKey)){
            var bucketName = 
                 ConfigurationManager.AppSettings["bucketName"]
                .ToString() + DownloadPath;
            GetPreSignedUrlRequest request1 = 
               new GetPreSignedUrlRequest(){
                  BucketName = bucketName,
                  Key = originalName,
                  Expires = DateTime.Now.AddMinutes(5)
               };

            string url = client.GetPreSignedURL(request1);
            return Redirect(url);
         }
     }
     catch (Exception)
     {
         failure = "File download failed. Please try after some time.";   
     }              
 }

只要對象沒有公共讀取策略,沒有簽名的用戶就無法訪問對象。

此外,您必須使用using周圍AmazonS3Client以便快速處置網絡資源,或只使用一個靜態實例AmazonS3Client ,將減少不必要的分配和釋放。

據我所知,您希望從服務器到S3進行“反向代理”。 非常有用的文章如何使用Nginx,你可以在這里找到: https ://stackoverflow.com/a/44749584

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM