我必须从aws S3 async下载一个文件.我有一个锚标签,点击它时,一个方法将在控制器中命中下载.该文件应该在浏览器底部开始下载,就像其他文件下载一样.
在视图中
Click here
在控制器中
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
给客户才能显示进度.浏览器没有关于它将接收多少数据的信息.
如果查看方法FileStreamResult
使用的类的来源File
,它不会通知客户"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
around AmazonS3Client
来快速处理网络资源,或者只使用一个静态实例来AmazonS3Client
减少不必要的分配和释放.