繁体   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