我需要在ASP.NET MVC中实现文件下载。在网上搜索,我找到了这样的代码:
public ActionResult GetFile()
{
return File(filename, "text/csv", Server.UrlEncode(filename));
}
这很好,但我想动态创建此文件的内容。
我意识到我可以动态创建文件,然后使用上面的语法下载该文件。但是,如果我能直接将我的内容直接写入回复,那会不会更有效率?这在MVC中是否可行?
答案 0 :(得分:14)
这是我最终使用的代码的过度简化版本。它满足了我的需求。
[HttpGet]
public ActionResult GetFile()
{
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=myfile.csv");
Response.ContentType = "text/csv";
// Write all my data
Response.Write(...);
Response.End();
// Not sure what else to do here
return Content(String.Empty);
}
答案 1 :(得分:3)
我很确定这是FileStreamResult的作用。但如果您不想使用它,只需将其写入响应即可。
答案 2 :(得分:3)
如果您想将其作为文件下载,那么您可以尝试@Tungano建议的自定义ActionResult
,否则如果您想直接进入响应,则内置ContentResult
会执行但是它可以使用简单的字符串,在复杂的场景中你必须扩展它。
public class CustomFileResult : FileContentResult
{
public string Content { get; private set; }
public string DownloadFileName { get; private set; }
public CustomFileResult(string content, string contentType, string downloadFileName)
: base(Encoding.ASCII.GetBytes(content), contentType)
{
Content = content;
DownloadFileName = downloadFileName;
}
public override void ExecuteResult(ControllerContext context)
{
context.HttpContext.Response.AppendHeader("Content-Disposition", "attachment; filename=" + DownloadFileName);
base.ExecuteResult(context);
}
}
public class BlogController : Controller
{
public ActionResult Index()
{
return View();
}
public CustomFileResult GetMyFile()
{
return CustomFile("Hello", "text/plain", "myfile.txt");
}
protected internal CustomFileResult CustomFile(string content, string contentType, string downloadFileName)
{
return new CustomFileResult(content, contentType, downloadFileName);
}
}
答案 3 :(得分:3)
另一种解决方案是使用接受流的File()重载。
在我的情况下,我需要从Controller Action生成一个csv,所以它有点像这样:
[HttpGet]
public ActionResult DownloadInvalidData(int fileId)
{
string invalidDataCsv = this.importService.GetInvalidData(fileId);
string downloadFileName = "error.csv";
var stream = new MemoryStream();
var writer = new StreamWriter(stream);
writer.Write(invalidDataCsv);
writer.Flush();
stream.Position = 0;
return File(stream, "text/csv", downloadFileName);
}
请注意,在将其传递给File()函数之前,应该不处理Stream或StreamWriter,因为处理它们会关闭流,使其无法使用。
答案 4 :(得分:2)
您可以直接写入Response.OutputStream,类似于流式传输到文件的方式。为了保持可测试性和MVC'ish,你可以创建自己的ActionResult类来执行传递它的模型对象的流式传输。