C# MVC 从 S3 异步下载大文件

标签 c# asp.net-mvc amazon-s3

我必须从 aws S3 async 下载文件。我有一个 anchor 标记,单击它会在 Controller 中点击一个方法进行下载。该文件应该在浏览器底部开始下载,就像其他文件下载一样。

在 View 中

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

在 Controller 中

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 来交付非公共(public) 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.";   
     }              
 }

只要对象没有公共(public)读取策略,用户就无法在不签名的情况下访问对象。

此外,您必须在 AmazonS3Client 周围使用 using 以便快速处理网络资源,或者只使用 AmazonS3Client 的一个静态实例,它将减少不必要的分配和释放。

关于C# MVC 从 S3 异步下载大文件,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41762520/

相关文章:

c# - 在 asp.net mvc 中打开 .aspx 文件作为 cshtml 的部分 View

amazon-s3 - Boto3 ContentDisposition 内联不起作用

amazon-s3 - 无法验证以下目标配置(S3 到 SQS)

amazon-web-services - 如何将Google Analytics(分析)查询到S3

c# - 如何将 XDocument 的 XML 内容保存为 .xml 文件?

c# - 父类中的属性 - 可以更改子类中的属性名称吗?

c# - 字符串数组转换为准备好进行 JSON 格式化的字符串

asp.net-mvc - 使用 Glimpse 获取 InvalidCastException,即使它尚未安装。我该如何解决?

c# - 使用 WriteableBitmap 的缓冲区大小不足?

单选按钮上的 JQuery 单击未捕获抛出 TypeError : Cannot read property 'indexOf' of undefined