在ASP.NET Web API中从控制器返回二进制文件

我正在使用ASP.NET MVC的新WebAPI来处理Web服务,它将提供二进制文件,主要是.cab.exe文件。

下面的控制器方法似乎起作用,这意味着它返回一个文件,但它将内容类型设置为application/json

public HttpResponseMessage<Stream> Post(string version, string environment, string filetype)
{
    var path = @"C:Temptest.exe";
    var stream = new FileStream(path, FileMode.Open);
    return new HttpResponseMessage<Stream>(stream, new MediaTypeHeaderValue("application/octet-stream"));
}

有一个更好的方法吗?


尝试使用一个简单的HttpResponseMessage并将其Content属性设置为StreamContent

// using System.IO;
// using System.Net.Http;
// using System.Net.Http.Headers;

public HttpResponseMessage Post(string version, string environment,
    string filetype)
{
    var path = @"C:Temptest.exe";
    HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
    var stream = new FileStream(path, FileMode.Open, FileAccess.Read);
    result.Content = new StreamContent(stream);
    result.Content.Headers.ContentType = 
        new MediaTypeHeaderValue("application/octet-stream");
    return result;
}

有关使用的stream一些注意事项:

  • 您不能调用stream.Dispose() ,因为Web API在处理控制器方法的result以将数据发送回客户端时仍然需要访问它。 因此,不要使用using (var stream = …)块。 Web API将为您处理流。

  • 确保流的当前位置设置为0(即流的数据的开始)。 在上面的例子中,这是一个给定的,因为你只是刚刚打开文件。 但是,在其他情况下(例如,当您首次将一些二进制数据写入MemoryStream ),请确保stream.Seek(0, SeekOrigin.Begin); 或设置stream.Position = 0;

  • 通过文件流,明确指定FileAccess.Read权限可以帮助防止Web服务器上的访问权限问题; IIS应用程序池帐户通常只能读取/列出/执行wwwroot的访问权限。


  • 对于Web API 2 ,您可以实现IHttpActionResult 。 这是我的:

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

    然后在你的控制器中这样的东西:

    [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忽略具有扩展名的请求,以便请求将其发送给控制器:

    <!-- web.config -->
    <system.webServer>
      <modules runAllManagedModulesForAllRequests="true"/>
    

    虽然建议的解决方案工作正常,但还有另一种方法可以从控制器返回一个字节数组,响应流格式正确:

  • 在请求中,设置标题“Accept:application / octet-stream”。
  • 在服务器端,添加一个媒体类型格式化程序来支持这种MIME类型。
  • 不幸的是,WebApi没有包含任何“application / octet-stream”格式化器。 在GitHub上有一个实现:BinaryMediaTypeFormatter(为了使它适用于webapi 2,方法签名已更改,有一些小修改)。

    您可以将此格式化程序添加到您的全局配置中:

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

    如果请求指定了正确的Accept头,则WebApi现在应该使用BinaryMediaTypeFormatter

    我更喜欢这个解决方案,因为返回byte []的动作控制器测试起来更加舒适。 尽管如此,如果您想返回另一种内容类型而不是“application / octet-stream”(例如“image / gif”),另一种解决方案允许您进行更多控制。

    链接地址: http://www.djcxy.com/p/65895.html

    上一篇: Returning binary file from controller in ASP.NET Web API

    下一篇: Does IMDB provide an API?