您必须发送ContentLength
向客户端显示进度。浏览器没有关于它将接收多少数据的信息。
如果你看一下来源FileStreamResult
类,被使用File
方法,它不会通知客户端有关“Content-Length”的信息。https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/FileStreamResult.cs https://aspnetwebstack.codeplex.com/SourceControl/latest#src/System.Web.Mvc/FileStreamResult.cs
替换这个,
return File(response, mimeType, downLoadName);
with
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 对象,其生存时间只有几秒钟。你可以简单地使用预签名 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
这将减少不必要的分配和取消分配。