【问题标题】:asp.net core - How to serve static file with no extensionasp.net core - 如何提供没有扩展名的静态文件
【发布时间】:2018-02-13 14:40:24
【问题描述】:

ASP.NET Core 根据文件的 mime 类型从 wwwroot 文件夹中提供文件。但是如何让它提供一个没有扩展名的文件呢?

例如,Apple 要求您的应用程序中有一个端点 /apple-app-site-association 用于某些应用程序集成。如果您将一个名为 apple-app-site-association 的文本文件添加到您的 wwwroot 中,它将不起作用。

我尝试过的一些事情:

1) 提供无扩展时的映射:

var provider = new FileExtensionContentTypeProvider();
provider.Mappings[""] = "text/plain";
app.UseStaticFiles(new StaticFileOptions
            {
                ContentTypeProvider = provider
            });

2) 添加应用重写:

var options = new RewriteOptions()
.AddRewrite("^apple-app-site-association","/apple-app-site-association.txt", false)

两者都不起作用,唯一起作用的是.AddRedirect,如果可能的话,我宁愿不使用它。

【问题讨论】:

    标签: asp.net-core


    【解决方案1】:

    与其使用静态文件,我认为你最好为它创建一个控制器:

    using Microsoft.AspNetCore.Hosting;
    using Microsoft.AspNetCore.Mvc;
    using System.IO;
    
    namespace MyApp.Controllers {
        [Route("apple-app-site-association")]
        public class AppleController : Controller {
            private IHostingEnvironment _hostingEnvironment;
    
            public AppleController(IHostingEnvironment environment) {
                _hostingEnvironment = environment;
            }
    
            [HttpGet]
            public async Task<IActionResult> Index() {
                return Content(
                    await File.ReadAllTextAsync(Path.Combine(_hostingEnvironment.WebRootPath, "apple-app-site-association")),
                    "text/plain"
                );
            }
        }
    }
    

    这假设您的 apple-app-site-association 文件位于您的 wwwroot 文件夹中。

    【讨论】:

    • 大声笑,这几乎正是我放弃并恢复的 - 虽然感觉有些不对劲,但它确实有效!
    • 如果它很愚蠢但有效,那么它并不愚蠢! :)
    • 像这样,您不需要 wwwroot 中的实际文件。我在 Apple 文件中遇到了同样的问题 - 我已将凭据放入 appsettings 并在代码中生成了 json。
    【解决方案2】:

    我认为最简单的方法是将 apple-app-site-association 文件添加到应用程序根文件夹中的 .well-known 文件夹中,如所述此处:[https://developer.apple.com/documentation/safariservices/supporting_associated_domains] 然后允许从您的代码访问它,如下所示(Startup.cs):

     // to allow access to apple-app-site-association file
    app.UseStaticFiles(new StaticFileOptions()
    {
        FileProvider = new PhysicalFileProvider(Path.Combine(env.ContentRootPath, @".well-known")),
        RequestPath = new PathString("/.well-known"),
        DefaultContentType = "application/json",
        ServeUnknownFileTypes = true,
    });

    在 AWS 无服务器应用程序 (.NET Core 3.1) 中测试

    【讨论】:

      【解决方案3】:

      添加替代解决方案。您必须将 ServeUnknownFileTypes 设置为 true,然后设置默认内容类型。

              app.UseStaticFiles(new StaticFileOptions
              {
                  ServeUnknownFileTypes = true,
                  DefaultContentType = "text/plain"
              });
      

      【讨论】:

      • 拒绝投票,因为这会增加安全风险,如 ASP Core 文档中所述。公认的答案是在不打开所有文件类型的情况下将要提供的文件“列入白名单”的最佳方式。
      • 如果您担心安全性,您可以使用特定的 PhysicalFileProvider 使用此选项缩小服务文件的范围,或者将您自己的 IFileProvider 实现为 StaticFileOptions.FileProvider 属性。
      • 警告启用 ServeUnknownFileTypes 存在安全风险。默认情况下禁用,不鼓励使用。
      • 正是我所需要的谢谢。这是开发工作,我不需要担心深度安全性。如果您希望默认为二进制文件,请使用“application/octet-stream”
      【解决方案4】:

      更简单的选择可能是将具有适当扩展名的文件放在服务器上,然后使用 URL 重写,如下所示。

      app.UseRewriter(new RewriteOptions()
          .AddRewrite("(.*)/apple-app-site-association", "$1/apple-app-site-association.json", true));
      

      【讨论】:

      • 最佳答案!没有安全风险,例如允许所有未知的静态文件类型,也没有通过创建控制器来返回简单的 json 文件的开销。
      • 这在 .NET 6 中对我不起作用。我不得不使用 app.UseRewriter(new RewriteOptions().AddRewrite("^apple-app-site-association$", "/apple-app-site-association.json", true));