使用FileResult在Asp.Net MVC中下载任何类型的文件?

我曾经建议我应该使用FileResult来允许用户从我的Asp.Net MVC应用程序下载文件。 但是我能找到的唯一例子总是与图像文件(指定内容类型图像/ jpeg)有关。

但是,如果我不知道文件类型呢? 我希望用户能够从我的网站的filearea几乎下载任何文件。

我已经阅读了一个这样做的方法(请参阅前面的代码),实际上它工作正常,除了一件事情:在另存为对话框中出现的文件的名称从文件路径连接到下划线folder_folder_file.ext)。 此外,似乎人们认为我应该返回一个FileResult,而不是使用这个自定义类,我发现BinaryContentResult。

任何人都知道在MVC中做这种下载的“正确”方式?

编辑:我得到了答案(下面),但只是想我应该发布完整的工作代码,如果别人有兴趣:

public ActionResult Download(string filePath, string fileName) { string fullName = Path.Combine(GetBaseDir(), filePath, fileName); byte[] fileBytes = GetFile(fullName); return File( fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName); } byte[] GetFile(string s) { System.IO.FileStream fs = System.IO.File.OpenRead(s); byte[] data = new byte[fs.Length]; int br = fs.Read(data, 0, data.Length); if (br != fs.Length) throw new System.IO.IOException(s); return data; } 

你可以指定通用的八位字节流MIME类型:

 public FileResult Download() { byte[] fileBytes = System.IO.File.ReadAllBytes(@"c:\folder\myfile.ext"); string fileName = "myfile.ext"; return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, fileName); } 

MVC框架本身支持这个。 System.Web.MVC.Controller.File控制器提供了通过名称 / 流 / 数组返回文件的方法。

例如使用文件的虚拟路径,您可以执行以下操作。

 return File(virtualFilePath, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(virtualFilePath)); 

如果您使用的是.NET Framework 4.5,则使用MimeMapping.GetMimeMapping (字符串FileName)来获取文件的MIME类型。 这是我在我的行动中使用它的方式。

 return File(Path.Combine(@"c:\path", fileFromDB.FileNameOnDisk), MimeMapping.GetMimeMapping(fileFromDB.FileName), fileFromDB.FileName); 

菲尔·哈克有一个很好的文章 ,他创建了一个Custome文件下载行动结果类。 您只需要指定文件的虚拟路径和要保存的名称即可。

我曾经使用它,这是我的代码。

  [AcceptVerbs(HttpVerbs.Get)] public ActionResult Download(int fileID) { Data.LinqToSql.File file = _fileService.GetByID(fileID); return new DownloadResult { VirtualPath = GetVirtualPath(file.Path), FileDownloadName = file.Name }; } 

在我的例子中,我存储的文件的物理路径,所以我用这个帮助器的方法 – 我发现我不记得的地方 – 将其转换为虚拟路径

  private string GetVirtualPath(string physicalPath) { string rootpath = Server.MapPath("~/"); physicalPath = physicalPath.Replace(rootpath, ""); physicalPath = physicalPath.Replace("\\", "/"); return "~/" + physicalPath; } 

这是从Phill Haack的文章中获得的完整课程

 public class DownloadResult : ActionResult { public DownloadResult() {} public DownloadResult(string virtualPath) { this.VirtualPath = virtualPath; } public string VirtualPath { get; set; } public string FileDownloadName { get; set; } public override void ExecuteResult(ControllerContext context) { if (!String.IsNullOrEmpty(FileDownloadName)) { context.HttpContext.Response.AddHeader("content-disposition", "attachment; filename=" + this.FileDownloadName) } string filePath = context.HttpContext.Server.MapPath(this.VirtualPath); context.HttpContext.Response.TransmitFile(filePath); } } 

感谢Ian Henry

如果您需要从MS SQL Server获取文件,则是解决方案。

 public FileResult DownloadDocument(string id) { if (!string.IsNullOrEmpty(id)) { try { var fileId = Guid.Parse(id); var myFile = AppModel.MyFiles.SingleOrDefault(x => x.Id == fileId); if (myFile != null) { byte[] fileBytes = myFile.FileData; return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, myFile.FileName); } } catch { } } return null; } 

其中AppModelEntityFramework模型和MyFiles在您的数据库中呈现FileDataMyFiles表中的varbinary(MAX)

它的简单只是给你的物理路径directoryPath与文件名

 public FilePathResult GetFileFromDisk(string fileName) { return File(directoryPath, "multipart/form-data", fileName); } 

GetFile应该关闭文件(或在使用中打开它)。 然后你可以在转换成字节后删除文件 – 下载将在该字节缓冲区上完成。

  byte[] GetFile(string s) { byte[] data; using (System.IO.FileStream fs = System.IO.File.OpenRead(s)) { data = new byte[fs.Length]; int br = fs.Read(data, 0, data.Length); if (br != fs.Length) throw new System.IO.IOException(s); } return data; } 

所以在你的下载方法中

  byte[] fileBytes = GetFile(file); // delete the file after conversion to bytes System.IO.File.Delete(file); // have the file download dialog only display the base name of the file return File(fileBytes, System.Net.Mime.MediaTypeNames.Application.Octet, Path.GetFileName(file));