C# 从控制器下载文件

C# 从控制器下载文件,c#,asp.net,asp.net-core,downloadfile,C#,Asp.net,Asp.net Core,Downloadfile,在Aspnet5 RC1 update1 web应用程序中,尝试执行与Response.BinaryWrite相同的操作,在旧的AspNet应用程序中下载文件。用户需要在客户端获得一个弹出的保存对话框 使用以下代码时,客户端会出现一个弹出提示以保存文件 public void Configure(IApplicationBuilder app) { //app.UseIISPlatformHandler(); //app.UseStaticFiles(); //app.U

在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);
    });
}
但当控制器的操作中使用相同的代码时,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,只有带有jquery ajax调用的纯html。

您真的需要
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"
}

我总是使用这段代码来下载文件,它对我来说很好。我根据你的代码修改了它

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);
}

我认为直接写回复的建议答案不太正确,因为直接访问回复不是你应该在控制器中思考的事情。有更好的方法,如以下所述:


其主要思想是返回ActionResult,而不是直接干扰响应。据我记忆所及,在以前的ASP.NET中已经有一些类似的类,但新的ASP.NET似乎至少目前还缺少它。您只需要在控制器中返回
FileResult

您是使用response.body.write设置的,还是可以从操作中返回httpfile您可以在
wait response.body.WriteAsync(
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);
        }
    }
}