数字营销 · Web开发 · 基础设施

网站图片应该上传多少个尺寸?动态裁剪可能是更好的方案

网站不同页面和终端需要不同尺寸的图片,传统方式容易生成大量无用缩略图。本文介绍动态图片裁剪的实现思路、缓存策略和接口限制,并介绍 Domai CMS 内置的动态裁剪功能。

我们在做网站的时候,经常会遇到一个问题:同一张图片,在不同页面上,需要的尺寸可能完全不一样。

比如首页的文章封面可能需要 600×400,列表页可能只需要 300×200,到了详情页,又可能需要一张宽度 1200 像素的大图。

除了不同页面之外,电脑端、平板端和手机端,对图片尺寸的要求也不一样。

那么,一张原图到底应该提前生成多少个尺寸?

传统做法:上传的时候提前生成

传统的网站,通常会在图片上传的时候,就提前生成几个常用尺寸。例如 WordPress,上传一张图片之后,会自动生成缩略图、中等尺寸、大尺寸等多个版本,主题和插件也可以继续注册新的图片尺寸。

这种方式当然有它的优点,用户访问页面的时候,不需要再处理图片,直接读取已经生成好的文件就可以。

但问题也很明显:这些尺寸不一定真的会被使用。

一个网站可能只上传了一万张原图,如果每张图片都自动生成五六个尺寸,服务器最后就可能出现五六万个,甚至更多的图片文件。

而且网站不是开发完成之后就永远不变,网站改版以后,页面布局会变化,图片尺寸也会跟着变化。

以前生成的尺寸可能已经不再使用,新的尺寸又需要重新生成,时间一长,服务器里就很容易积累大量没有实际用途的图片文件。

为什么不在真正需要的时候再裁剪?

所以现在可以采用另一种方式:图片上传的时候,只保存原图;页面真正需要某个尺寸的时候,再动态裁剪。

例如页面需要一张 600×400 的图片,就通过图片地址告诉服务器需要这个尺寸。服务器收到请求后,读取原图,按照指定的尺寸进行缩放或裁剪,然后把处理后的图片返回给浏览器。

列表页需要 300×200,就请求 300×200。

手机端只需要宽度 480 像素,也可以请求对应尺寸。

这样就不需要在上传图片的时候,提前猜测以后所有页面可能会用到哪些规格。页面需要什么尺寸,就处理什么尺寸。

这种方式最大的特点就是灵活。网站后面改版了,需要换一个尺寸,也不需要重新处理整个图片库,只需要按照新的尺寸请求即可。

现在的服务器已经足够做这件事情

很多人可能会担心:图片每次请求都需要重新裁剪,会不会非常消耗服务器?

其实这个问题放在十几年前,确实值得认真考虑。但现在大多数服务器的 CPU 性能已经足够完成普通网站中的图片缩放和裁剪。对于访问量并不高的企业网站、博客或者内容型网站来说,偶尔进行一次图片处理,通常不会带来特别大的压力。所以从现在的服务器环境来看,动态裁剪已经完全具备实际应用条件。

但这里又会出现另外一个问题:裁剪之后的图片,要不要保存?

动态裁剪之后,要不要缓存?

很多人的第一反应是:第一次请求 600×400 的时候进行裁剪,然后把结果保存下来。下一次再请求 600×400,就直接读取已经生成的图片。这种思路本身没有问题。

我在九年前开源过一个叫 Responsive-Image 的项目,当时采用的就是动态裁剪加文件缓存的方式。第一次请求某个尺寸的时候,服务器生成图片,同时把结果保存下来。以后再请求相同尺寸,就直接读取缓存文件。

按照当时的服务器性能和网络环境,这是一种比较合理的方案。但现在重新来看,我认为大部分普通网站其实没有必要永久保存这些裁剪结果。

永久缓存可能带来的问题

第一个问题就是:缓存很容易把服务器空间慢慢占满。如果图片尺寸参数完全开放,理论上可以请求出非常多不同的尺寸。

比如:

500×300
501×300
502×300
500×301
500×302

每一种参数组合,都有可能生成一个新的缓存文件。如果没有做好尺寸限制和缓存清理,最后生成的图片甚至可能比 WordPress 自动生成的缩略图还多。这些文件不仅会占用磁盘空间,还会产生大量小文件。服务器备份、网站迁移以及文件管理,都会因此变得更加麻烦。

第二个问题是:

现在很多网站其实没有这么大的图片处理压力。如果一个企业网站每天只有几百、几千甚至更少的图片请求,为了节省一点点图片处理时间,却长期保存成千上万个缓存文件,我觉得并不一定划算。

所以动态裁剪可以做。但缓存怎么做,需要根据网站的实际访问量来决定。

普通网站可以不做永久文件缓存,或者只做短时间缓存。

访问量比较大的网站,则可以考虑把缓存交给 CDN、反向代理或者对象存储处理,而不是让网站服务器一直生成并永久保存大量文件。

动态裁剪接口也不能完全没有限制

动态裁剪还有一个容易被忽略的问题。不能让用户随便请求任意尺寸。否则别人可以不断请求:

500×300
501×300
502×300
503×300……

每一次请求都有可能触发一次新的图片处理。这样不仅浪费 CPU 和内存,严重的时候甚至可以让图片处理接口本身成为一个攻击入口。所以实际开发中,还是需要对参数进行限制。例如限制最大宽度和高度,只开放几个常用的尺寸档位,并对传入参数进行严格校验。这样既能满足正常的网站使用需求,也可以避免有人通过不断请求不同尺寸来消耗服务器资源。

这套方案,我自己已经用了很多年

动态裁剪其实并不是什么新的概念。我自己使用这种方式已经有十多年了。以前在企业里做网站的时候,我们基本也是采用这种方式来处理图片。对于企业网站来说,这种方式最大的优势并不是“技术有多新”,而是网站以后怎么改,图片处理都不用被最初的尺寸规划限制住。页面需要什么尺寸,就请求什么尺寸。电脑端和手机端需要不同尺寸,也可以分别处理。网站改版之后,需要新的图片规格,也不需要重新生成整个图片库。

本站就支持图片动态裁剪

本站使用的是我开发的 Domai CMS,图片动态裁剪本身就是系统内置的功能。不需要额外安装图片处理插件,也不需要单独开发一套图片服务,只需要在图片地址后面增加:

!宽度x高度

就可以指定需要的图片尺寸。例如:

https://www.hitoy.org/dm-content/uploads/v7nxlch3.png!100x100

就表示需要一张 100×100 的图片。

网站会根据这个参数,在请求图片时进行相应的缩放和裁剪。所以同一张原图,可以根据首页、列表页、详情页以及不同终端的实际需求,直接生成对应尺寸的图片。整个调用方式非常简单,但已经可以满足企业网站大部分常见的图片裁剪需求。你现在看到的本站缩略图和文章图片,就可以通过这种方式进行处理。

如果对具体的实现方式感兴趣,也可以直接查看本站的源代码,或者联系我交流。

评论0

欢迎分享你的看法,也欢迎补充不同的实践经验。