解决MySql布尔型新旧版本兼容问题,采用枚举来表示布尔型的数据表。由正向工程赋值
大石头 authored at 2018-05-15 21:21:05
2.09 KiB
X
using NewLife.Remoting;

namespace NewLife.Http;

/// <summary>静态文件处理器</summary>
/// <remarks>将指定目录映射为静态文件服务,支持常见的文件类型</remarks>
public class StaticFilesHandler : IHttpHandler
{
    #region 属性
    /// <summary>映射路径。如 /js/</summary>
    public String Path { get; set; } = null!;

    /// <summary>内容目录。如 /wwwroot/js</summary>
    public String ContentPath { get; set; } = null!;
    #endregion

    /// <summary>处理请求</summary>
    /// <param name="context">Http上下文</param>
    public virtual Task ProcessRequestAsync(IHttpContext context)
    {
        if (!context.Path.StartsWithIgnoreCase(Path)) throw new ApiException(ApiCode.NotFound, $"File {context.Path} not found");

        var file = context.Path[Path.Length..];
        file = ContentPath.CombinePath(file);

        // 路径安全检查,防止目录穿越。基路径先补上目录分隔符再比对:
        // 否则内容目录 D:\www\js 会放行 D:\www\js2 这类同前缀的兄弟目录
        var baseDir = ContentPath.GetFullPath().EnsureEnd(System.IO.Path.DirectorySeparatorChar + "");
        if (!file.GetFullPath().StartsWithIgnoreCase(baseDir))
            throw new ApiException(ApiCode.NotFound, $"File {context.Path} not found");

        var fi = file.AsFile();
        if (!fi.Exists) throw new ApiException(ApiCode.NotFound, $"File {context.Path} not found");

        var contentType = GetContentType(fi.Extension) ?? "application/octet-stream";

        // 流式发送文件内容:流所有权移交响应(发送完成后释放),大文件不物化到内存
        var fs = fi.OpenRead();
        context.Response.ContentType = contentType;
        context.Response.BodyStream = fs;

        return TaskEx.CompletedTask;
    }

    /// <summary>根据文件扩展名获取MIME类型</summary>
    /// <param name="extension">文件扩展名(含点号)</param>
    /// <returns>MIME类型;未知类型返回null</returns>
    protected virtual String? GetContentType(String extension) => MimeHelper.GetContentType(extension);
}