【问题标题】:Cannot get file extension properly in Web API无法在 Web API 中正确获取文件扩展名
【发布时间】:2018-09-20 23:22:35
【问题描述】:

在我基于 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 Controller 中使用相同的方法时,没有这种 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 无法获取类型是 application/octet-stream。那么,有什么想法可以为 Web Api 解决这个问题吗???

【问题讨论】:

  • 扩展名不是已经在文件名中了吗?
  • 不,扩展名不是

标签: c# asp.net-mvc file asp.net-web-api


【解决方案1】:

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

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

【讨论】:

    【解决方案2】:

    你必须安装像 MediaTypeMap 这样的 Nuget 包,或者编写一个自定义方法来返回基于 MimeType 的文件的 .ext。 请参阅 this 链接了解所有 mime 详细信息。

    我添加了使用 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;
                }
    

    【讨论】:

      【解决方案3】:

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

      要从 mime 类型派生扩展,您可以使用其他人提到的某种映射字典。 Divyang Patel's answer 展示了如何做到这一点。

      另一个选项是从文件内容中试探性地派生扩展名(或 mime 类型)。我通常不会推荐此选项,因为它会占用大量资源,但为了完整起见,我想我会提及它。

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

      以下是包使用示例:

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

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

      对于您的用例,如果您应该选择走这条路,它的工作原理如下:

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

      无论如何,我都会努力为后续请求存储任何派生的文件扩展名。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-12-01
        • 1970-01-01
        • 1970-01-01
        • 2011-07-15
        • 1970-01-01
        • 1970-01-01
        • 2016-12-16
        • 1970-01-01
        相关资源
        最近更新 更多