美文网首页.NETdotNET计算机微刊
[解决方案] 自动调整图片

[解决方案] 自动调整图片

作者: gruan | 来源:发表于2017-09-14 18:03 被阅读0次
    • 项目源码
    • 原因: 图片尺寸/大小不一,没有规则,总共有300多G
    • 目标
      • 尽量不修改原有程序及架构, 以最小的代价使PC时代的图片库适应于移动端
      • 溯源 (要和源文件对应起来)
      • 可控 (预定义规则, 并不是随便进来一个请求都会得到处理)
      • 不处理第二次(如果已经处理过,直接输出, 否则处理并保存,以供下次请求直接使用)

    ASP.NET 和 NETCore 的解决方法不同. 本文分两部份


    ASP.NET

    利用 VirtualFile / VirtualPathProviderStaticFileHandler 完成虚拟文件解析.

    溯源

    溯源的最简单办法是新文件源文件 名称,路径 保持一至. 而且有规则可以依, 就得把规则加到文件名中. 综合以上两点, 可以比较以下几种访问方式:

    源: http://www.baidu.com/imgs/2017/09/09/abc.jpg
    
    1. http://www.xxx.com/imgs/2017/09/09/abc.auto.s1.jpg
    2. http://www.xxx.com/imgs/2017/09/09/abc.jpg?100x100
    3. http://www.xxx.com/img?source=/imgs/2017/09/09/abc.jpg&w=100&h=100
    
    • 第1种在文件名和扩展名中间插入了占位符 auto 和 规则 s1. 拿到源文件地址后, 要处理成这种格式的, 不大方便 (仅此而已)
    • 第2种没有强插, 但是多了后缀. 这个的坏处就多了去,
      • 首先, 有问号和没有问号的都代表的是同一个文件,尤其是同时显示源图,和新图的时候, 问题更加突出.
      • Windows 下, 问号 (?) 是不能出现在文件名中的 (Linux 下没有测试,不知道). 这条是违背了第4条目标的.
    • 第3种就不多说了,太LOW了,不在考虑范围内.

    综上所述, 我们这里选择第1种访问方式.
    但是要使用这种方式, 就有点为难了, 因为: 没有入口 !

    给个入口

    静态类型的文件,ASP.NET 默认不会经过程序处理. 你可以在 GlobalBeginRequest 里设置一下断点,看能不能进来.
    要想要程序可以处理静态文件,只需要在 web.config 里加入如下配置:

    <system.webServer>
      <validation validateIntegratedModeConfiguration="false"/>
      <handlers>
        <!--设置可以由该程序处理的文件类型,必须-->
        <add name="jpg" path="*.jpg" verb="GET" type="System.Web.StaticFileHandler"/>
        <add name="gif" path="*.gif" verb="GET" type="System.Web.StaticFileHandler"/>
        <add name="png" path="*.png" verb="GET" type="System.Web.StaticFileHandler"/>
      </handlers>
    </system.webServer>
    

    至此, 你可以在 GlobalBeginRequest 里写处理程序了.

    更进一层

    VirtualPathProvider , VirtualFile 这两个东西的用处很多, 不了解的,可以自行搜索一下.
    我了解的也不多, 只是在很久之前用它们取出 dll 中的母版页而已.这里我用它们来处理图片请求.

    • 首先, 在 GlobalApplication_Start 里注册 VirtualPathProvider:

      HostingEnvironment.RegisterVirtualPathProvider(new  VImgProvider(baseDir));
      

      VImgProvider 源码

    • 请求进入之后,首先会到 VImgProvider.FileExists 方法, 这里主要是判断进入的请求是不是可接受的图片类型, 目标文件是不是存在.

    • 然后进入 VImgFile.Open方法 源码

      1. 判断请求的文件是否存在, 如果存在,直接返回.
      2. 如果不存在, 判断进入的请求是否满足设定的规则.
      3. 如果满足规则, 从请求里拆分/解析/装配 源图片 的路径.
      4. 如果源图片 存在, 按规则对源图片进行缩放, 并将结果保存到同一目录下.
      5. 同样的请求第二次进来,只用走到第1步就可以返回了.

    为了方便添加修改规则,我定义了一个热插拔的 JsonConfig. 只需要修改 Cfgs/SizeTypes.json 即可:
    示例:

    {
      "Types": [
        {
          "name": "s1",
          "width": 100,
          "height": 100,
          "quality": 70
        },
        {
          "name": "s2",
          "width": 200,
          "height": 200,
          "quality": 70
        },
        {
          "name": "s3",
          "width": 113,
          "height": 128
        }
      ]
    }
    

    当然, 以经生成的图片要手动删除, 才能应用新的配置


    NETCore

    通过修改 StaticFile 中间件的 FileProvider 来实现.

    相对而言, NETCore 的实现要简单的多: 只需要修改 StaticFileMiddleware 的 FileProvider 即可.

    var ap = new AutoImgFileProvider(this.Configuration);
    //优先 WebRootFileProvider , 如果文件在它中能找得到,就不在去 AutoImageFileProvider 中在找一次了.
    var cp = new CompositeFileProvider(env.WebRootFileProvider, ap);
    var opt = new StaticFileOptions()
    {
        FileProvider = cp
    };
    
    app.UseStaticFiles(opt);
    

    需要添加 Nuget

    • Microsoft.Extensions.FileProviders.Composite
    • Microsoft.Extensions.FileProviders.Phyical

    AutoImgFileProvider 是对 PhyicalFileProvider 做了一层包装, 而不是继承.
    收到请求时 (GetFileInfo), 首先调用包装的 PhyicalFileProvider.GetFileInfo , 如果目标存在, 直接返回; 否则, 和ASP.NET的流程一样: 拆分/解析/组装/保存, 然后返回.

    NETCore 规则配置采用了独立的配置文件, 修改规则,只需修改:
    AutoImg.json 即可
    示例:

    {
      "AutoImg": {
        "BaseDir": "d:\\Imgs",
        "Types": [
          {
            "name": "s1",
            "width": 100,
            "height": 100
          },
          {
            "name": "s2",
            "width": 200,
            "height": 200
          },
          {
            "name": "s3",
            "width": 113,
            "height": 128
          }
        ]
      }
    }
    

    另附

    NETCore 下图片处理采用 ImageSharp , NET FX 下用的是 ImageProcessor.
    ImageSharp 不支持质量百分比.

    相关文章

      网友评论

        本文标题:[解决方案] 自动调整图片

        本文链接:https://www.haomeiwen.com/subject/piqdsxtx.html