我正在使用ASP.NET MVC的新WebAPI开发Web服务,该服务将提供二进制文件,主要是.cab
和.exe
文件。 web
如下控制器方法彷佛有效,这意味着它返回一个文件,可是将内容类型设置为application/json
: json
public HttpResponseMessage<Stream> Post(string version, string environment, string filetype) { var path = @"C:\Temp\test.exe"; var stream = new FileStream(path, FileMode.Open); return new HttpResponseMessage<Stream>(stream, new MediaTypeHeaderValue("application/octet-stream")); }
有一个更好的方法吗? api
你能够试试数组
httpResponseMessage.Content.Headers.Add("Content-Type", "application/octet-stream");
对于Web API 2 ,能够实现IHttpActionResult
。 这是个人: 服务器
using System; using System.IO; using System.Net; using System.Net.Http; using System.Net.Http.Headers; using System.Threading; using System.Threading.Tasks; using System.Web; using System.Web.Http; class FileResult : IHttpActionResult { private readonly string _filePath; private readonly string _contentType; public FileResult(string filePath, string contentType = null) { if (filePath == null) throw new ArgumentNullException("filePath"); _filePath = filePath; _contentType = contentType; } public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken) { var response = new HttpResponseMessage(HttpStatusCode.OK) { Content = new StreamContent(File.OpenRead(_filePath)) }; var contentType = _contentType ?? MimeMapping.GetMimeMapping(Path.GetExtension(_filePath)); response.Content.Headers.ContentType = new MediaTypeHeaderValue(contentType); return Task.FromResult(response); } }
而后在您的控制器中这样: app
[Route("Images/{*imagePath}")] public IHttpActionResult GetImage(string imagePath) { var serverPath = Path.Combine(_rootPath, imagePath); var fileInfo = new FileInfo(serverPath); return !fileInfo.Exists ? (IHttpActionResult) NotFound() : new FileResult(fileInfo.FullName); }
这是您能够告诉IIS忽略带有扩展名的请求的一种方法,以便该请求将其发送到控制器: async
<!-- web.config --> <system.webServer> <modules runAllManagedModulesForAllRequests="true"/>
虽然建议的解决方案能够正常工做,可是还有另外一种方法能够从控制器返回字节数组,而且响应流的格式正确: 测试
不幸的是,WebApi不包括“应用程序/八位字节流”的任何格式化程序。 在GitHub上有一个实现: BinaryMediaTypeFormatter (有一些小的改动以使其适用于webapi 2,更改了方法签名)。 this
您能够将此格式化程序添加到全局配置中: spa
HttpConfiguration config; // ... config.Formatters.Add(new BinaryMediaTypeFormatter(false));
若是请求指定了正确的Accept标头,则WebApi如今应该使用BinaryMediaTypeFormatter
。
我更喜欢这种解决方案,由于操做控制器返回byte []更易于测试。 可是,若是您要返回除“ application / octet-stream”(例如“ image / gif”)以外的其余内容类型,则另外一种解决方案使您能够更好地控制。
对于使用接受的答案中的方法下载至关大的文件时屡次调用API的问题的人,请将响应缓冲设置为true System.Web.HttpContext.Current.Response.Buffer = true;
这样能够确保在将整个二进制内容发送到客户端以前,先在服务器端对其进行缓冲。 不然,您将看到多个请求被发送到控制器,若是处理不当,文件将损坏。
您能够在API控制器方法中使用IActionResult接口,以下所示:
[HttpGet("GetReportData/{year}")] public async Task<IActionResult> GetReportData(int year) { // Render Excel document in memory and return as Byte[] Byte[] file = await this._reportDao.RenderReportAsExcel(year); return File(file, "application/vnd.openxmlformats", "fileName.xlsx"); }
此示例已简化,但应该理解这一点。 在.NET核心这个过程是如此比在.NET以前的版本更加简单-即没有设置响应类型,内容,标题等。
另外,固然,文件和扩展名的MIME类型将取决于我的需求。
参考: SO发帖人@NKosi