嗯,简单的答案似乎是:
在浏览器中看不到下载开始和进度,因为没有设置内容长度,所以浏览器无法从FileStreamResult.
所以,设置它应该足够了。对我来说,通过使用允许设置长度的东西扩展 ActionResult 效果最好:
public class FileStreamWithLengthResult : ActionResult
{
private Stream stream;
private string mimeType;
private string fileName;
private long contentLength;
public FileStreamWithLengthResult(Stream stream,string mimeType,string fileName)
{
this.stream = stream;
this.mimeType = mimeType;
this.fileName = fileName;
this.contentLength = stream.Length;
}
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);
stream.CopyTo(response.OutputStream);
}
}
那么Action代码就这么简单
public async Task<FileStreamWithLengthResult> Download()
{
IAmazonS3 s3Client = GetS3Client();
GetObjectRequest request = new GetObjectRequest
{
BucketName = bucketName,
Key = objectKey,
};
GetObjectResponse response = await s3Client.GetObjectAsync(request).ConfigureAwait(false);
return new FileStreamWithLengthResult(response.ResponseStream, "application/octet-stream", "SomeFile.exe");
}
根据this 的回答。
另外,不对我有用的是像这样设置“Content-Lenght”标题:
this.ControllerContext.HttpContext.Response.AddHeader("Content-Length", response.ResponseStream.Length.ToString()); //not worked
this.Response.AddHeader("Content-Length", response.ResponseStream.Length.ToString()); //not worked
this.HttpContext.Response.AddHeader("Content-Length", response.ResponseStream.Length.ToString()); //not worked
我想这些都指向同一个对象实例,但不知道为什么它不起作用。无论如何,自定义 FileStreamWithLengthResult 工作正常,看起来更优雅:)