從ASP.NET Web API中的控制器返回二進制文件

我正在使用ASP.NET MVC的新WebAPI開發Web服務,該服務將提供二進制文件,主要是.cab.exe文件。 web

如下控制器方法彷佛有效,這意味着它返回一個文件,可是將內容類型設置爲application/jsonjson

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


#1樓

你能夠試試數組

httpResponseMessage.Content.Headers.Add("Content-Type", "application/octet-stream");

#2樓

對於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"/>

#3樓

雖然建議的解決方案能夠正常工做,可是還有另外一種方法能夠從控制器返回字節數組,而且響應流的格式正確: 測試

  • 在請求中,設置標題「接受:應用程序/八位字節流」。
  • 在服務器端,添加媒體類型格式化程序以支持此mime類型。

不幸的是,WebApi不包括「應用程序/八位字節流」的任何格式化程序。 在GitHub上有一個實現: BinaryMediaTypeFormatter (有一些小的改動以使其適用於webapi 2,更改了方法簽名)。 this

您能夠將此格式化程序添加到全局配置中: spa

HttpConfiguration config;
// ...
config.Formatters.Add(new BinaryMediaTypeFormatter(false));

若是請求指定了正確的Accept標頭,則WebApi如今應該使用BinaryMediaTypeFormatter

我更喜歡這種解決方案,由於操做控制器返回byte []更易於測試。 可是,若是您要返回除「 application / octet-stream」(例如「 image / gif」)以外的其餘內容類型,則另外一種解決方案使您能夠更好地控制。


#4樓

對於使用接受的答案中的方法下載至關大的文件時屢次調用API的問題的人,請將響應緩衝設置爲true System.Web.HttpContext.Current.Response.Buffer = true;

這樣能夠確保在將整個二進制內容發送到客戶端以前,先在服務器端對其進行緩衝。 不然,您將看到多個請求被髮送到控制器,若是處理不當,文件將損壞。


#5樓

對於使用.NET Core的用戶:

您能夠在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

相關文章
相關標籤/搜索