Jos*_*arl 313 asp.net asp.net-mvc asp.net-web-api
我正在使用ASP.NET MVC的新的WebAPI的网络服务,将成为了二进制文件,主要是.cab和.exe文件.
以下控制器方法似乎有效,这意味着它返回一个文件,但它将内容类型设置为application/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"));
}
Run Code Online (Sandbox Code Playgroud)
有一个更好的方法吗?
car*_*ira 501
尝试使用简单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:\Temp\test.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;
}
Run Code Online (Sandbox Code Playgroud)
关于stream使用的一些注意事项:
您不能调用stream.Dispose(),因为Web API在处理控制器方法时仍需要能够访问它result以将数据发送回客户端.因此,不要使用using (var stream = …)块.Web API将为您配置流.
确保流的当前位置设置为0(即流的数据的开头).在上面的例子中,这是给定的,因为你刚刚打开了文件.但是,在其他情况下(例如,当您首次将一些二进制数据写入a时MemoryStream),请确保stream.Seek(0, SeekOrigin.Begin);或设置stream.Position = 0;
使用文件流,显式指定FileAccess.Read权限可以帮助防止Web服务器上的访问权限问题; IIS应用程序池帐户通常只具有对wwwroot的读/列/执行访问权限.
Ron*_*rby 133
对于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);
}
}
Run Code Online (Sandbox Code Playgroud)
然后在你的控制器中这样的事情:
[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);
}
Run Code Online (Sandbox Code Playgroud)
这里有一种方法可以告诉IIS忽略具有扩展名的请求,以便请求将其发送给控制器:
<!-- web.config -->
<system.webServer>
<modules runAllManagedModulesForAllRequests="true"/>
Run Code Online (Sandbox Code Playgroud)
虽然建议的解决方案工作正常,但还有另一种方法从控制器返回一个字节数组,响应流格式正确:
不幸的是,WebApi不包括"application/octet-stream"的任何格式化程序.GitHub上有一个实现:BinaryMediaTypeFormatter(有一些小的改编使它适用于webapi 2,方法签名改变了).
您可以将此格式化程序添加到全局配置中:
HttpConfiguration config;
// ...
config.Formatters.Add(new BinaryMediaTypeFormatter(false));
Run Code Online (Sandbox Code Playgroud)
BinaryMediaTypeFormatter如果请求指定了正确的Accept标头,WebApi现在应该使用.
我更喜欢这个解决方案,因为返回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");
}
Run Code Online (Sandbox Code Playgroud)
此示例已简化,但应该理解这一点。在.NET核心这个过程是这样比在.NET之前的版本更加简单-即没有设置响应类型,内容,标题等。
另外,当然,文件和扩展名的MIME类型将取决于个人需求。
参考:SO发帖人@NKosi
您正在使用的重载设置序列化格式化程序的枚举.您需要明确指定内容类型,如:
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
Run Code Online (Sandbox Code Playgroud)
你可以尝试
httpResponseMessage.Content.Headers.Add("Content-Type", "application/octet-stream");
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
263848 次 |
| 最近记录: |