在Aspnet5 RC1 update1 Web应用程序中,尝试与Response.BinaryWrite一样,在旧的AspNet应用程序中下载文件。用户需要在客户端获得弹出保存对话框。
使用以下代码时,客户端会出现一个弹出提示以保存文件。
public void Configure(IApplicationBuilder app)
{
//app.UseIISPlatformHandler();
//app.UseStaticFiles();
//app.UseMvc();
app.Run(async (objContext) =>
{
var cd = new System.Net.Mime.ContentDisposition {
FileName = "test.rar", Inline = false };
objContext.Response.Headers.Add("Content-Disposition", cd.ToString());
byte[] arr = System.IO.File.ReadAllBytes("G:\\test.rar");
await objContext.Response.Body.WriteAsync(arr, 0, arr.Length);
});
}
但是当在Controller的操作中使用相同的代码时,app.Run被注释掉,保存弹出窗口没有出现,内容只是呈现为文本。
[Route("[controller]")]
public class SampleController : Controller
{
[HttpPost("DownloadFile")]
public void DownloadFile(string strData)
{
var cd = new System.Net.Mime.ContentDisposition {
FileName = "test.rar", Inline = false };
Response.Headers.Add("Content-Disposition", cd.ToString());
byte[] arr = System.IO.File.ReadAllBytes("G:\\test.rar");
Response.Body.WriteAsync(arr, 0, arr.Length);
需要的是,控制流需要来控制器,执行一些逻辑,然后将byte []响应内容发送到客户端,用户需要保存文件。没有cshtml,只是简单的html与jquery ajax调用。
答案 0 :(得分:8)
您真的需要HttpPost
属性吗?尝试删除它或改为使用HttpGet
:
public async void DownloadFile()
{
Response.Headers.Add("content-disposition", "attachment; filename=test.rar");
byte[] arr = System.IO.File.ReadAllBytes(@"G:\test.rar");
await Response.Body.WriteAsync(arr, 0, arr.Length);
}
更新:可能更容易使用FileStreamResult
:
[HttpGet]
public FileStreamResult DownloadFile() {
Response.Headers.Add("content-disposition", "attachment; filename=test.rar");
return File(new FileStream(@"G:\test.rar", FileMode.Open),
"application/octet-stream"); // or "application/x-rar-compressed"
}
答案 1 :(得分:0)
我总是使用这段代码下载文件,它对我来说很好。我将其改编为您的代码。
public ActionResult DownloadFile(string strData) {
var cd = new System.Net.Mime.ContentDisposition { FileName = "test.rar", Inline = false };
byte[] arr = System.IO.File.ReadAllBytes(@"G:\test.rar");
Response.ContentType = "application/x-rar-compressed";
Response.AddHeader("content-disposition", cd.ToString());
Response.Buffer = true;
Response.Clear();
Response.BinaryWrite(arr);
Response.End();
return new FileStreamResult(Response.OutputStream, Response.ContentType);
}
答案 2 :(得分:0)
我认为直接写入响应的建议答案并不完全正确,因为直接访问Response不是您应该在控制器中思考的内容。有更好的方法,例如这里描述:
http://forums.asp.net/t/2011115.aspx?How+to+download+a+file+from+a+path+in+asp+net+vnext+
public class FileResult : ActionResult
{
public FileResult(string fileDownloadName, string filePath, string contentType)
{
FileDownloadName = fileDownloadName;
FilePath = filePath;
ContentType = contentType;
}
public string ContentType { get; private set; }
public string FileDownloadName { get; private set; }
public string FilePath { get; private set; }
public async override Task ExecuteResultAsync(ActionContext context)
{
var response = context.HttpContext.Response;
response.ContentType = ContentType;
context.HttpContext.Response.Headers.Add("Content-Disposition", new[] { "attachment; filename=" + FileDownloadName });
using (var fileStream = new FileStream(FilePath, FileMode.Open))
{
await fileStream.CopyToAsync(context.HttpContext.Response.Body);
}
}
}
主要思想是返回ActionResult而不是直接搞乱Response。据我所知,在之前的ASP.NET中已经有类似的类,但似乎新的缺少它至少目前。您只需要在控制器中返回FileResult
。