无法在Web API中正确获取文件扩展名

我在ASP.NET MVC和Angular的项目构建中使用了一个方法并检索从数据库中存储的文件而没有任何问题:

[HttpPost] public ActionResult GetFile(int id) { var file= service.GetFileById(id); if (file.Data != null) { return File(file.Data, file.MimeType, file.Name); } return new EmptyResult(); } 

另一方面,当我想在我的Web Api控制器中使用相同的方法时,没有这种类型的File()方法,我在查看stackoverflow上的15-20解决方案之后尝试使用以下方法:

 [Route("api/Generate/{id}")] [AcceptVerbs("GET", "POST")] public HttpResponseMessage Generate(int id) { var data = service.GetFileByName(id); var stream = new MemoryStream(); var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(stream.ToArray()) }; result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = data.Name }; result.Content.Headers.ContentType = new MediaTypeHeaderValue(data.MimeType); return result; } 

但是,没有下载文件的扩展,我没有找到一个有用的方法,以便从mime类型获取文件扩展,如下所示(此方法从application / pdf获取文件类型,但如果mime类型是应用程序则无法获取/ octet-stream。所以,任何想法为Web Api解决这个问题???

如果无法在db中存储扩展名的文件名,则应按mime类型计算扩展名。

以下是关于反之亦然解决方案的答案。 您可以使用自己的映射表。 但是如果特定的mime类型会有多个扩展,那么你应该决定选择哪个

您必须像MediaTypeMap一样安装Nuget包,或者编写一个基于MimeType返回文件的.ext的自定义方法。 请参阅此链接以获取所有哑剧详情。

我使用MediaTypeMap Nuget添加了获取文件扩展名的代码。

  using (MemoryStream stream = new System.IO.MemoryStream()) { var result = new HttpResponseMessage(HttpStatusCode.OK) { Content = new ByteArrayContent(stream.ToArray()) }; result.Content.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment") { FileName = data.Name + MimeTypeMap.GetExtension(data.MimeType) }; result.Content.Headers.ContentType = new MediaTypeHeaderValue(data.MimeType); var response = ResponseMessage(result); return response; } 

据我了解,您希望从手头的文件信息中获取文件扩展名。 我认为你有二进制文件内容,没有扩展名的文件名和mime类型(也就是内容类型)。

要从mime类型派生扩展,您可以使用某种映射字典,就像其他人提到的那样。 Divyang Patel的答案显示了你如何做到这一点。

另一种选择是从文件内容中启发式地派生扩展(或mime类型)。 我一般不会推荐这个选项,因为它是资源密集型的,但我想我会提到它的完整性。

TrID是我个人知道的唯一选择。 我确定还有其他人。 有一个CLI,一个.NET GUI和一个Nuget库 (我认为是非官方的)。

以下是包使用的示例:

 string extension = TrIDEngine.GetExtensionByFileContent(@"C:\path\to\file.???"); 

据我所知,这个库没有提供接受文件系统路径以外的任何东西的公共接口。 这是不幸的,因为在某些情况下,文件内容可以从文件系统之外的某处流式传输。

对于您的用例,如果您应该选择这条路线,这是它的工作方式:

  1. 将文件内容写入临时文件系统位置(如果您还没有可用于读取文件的文件路径)。
  2. 使用TrID派生扩展。
  3. 向客户端发送响应,包括派生文件扩展名和文件内容。
  4. 删除(或删除)已写入的任何临时文件。

在任何情况下,我都会努力为后续请求存储任何派生文件扩展名。