Apache 文件不存在跳转URL(实现指定尺寸的图片不存在,就自动生成图片)

时间:2022-10-01 00:12:35

前言

在做很多系统的时候,我们可能都有这样的需求:

在CMS中只维护一张图片,而这张图片在网站的很多地方都需要显示,而且显示的大小不同。

一般做法就是直接使用这张图片,在不同的地方使用 width 和 height 设定图片的显示大小。


场景需求

一般情况下这样做其实就可以了。如下这个场景,如果通过这样做,可能就不太合适了。

场景:CMS 有个海报管理功能,每个大的海报都是一张 1000*2000px 的图片,而且对海报的清晰度有一定的要求,质量不能太差,假定一个海报有 1MB。

然后在网站上有一个海报列表,每页显示20个海报。

这种情况下如果我们还用一张图片,通过 width 和 height 来设定图片显示大小的话,那就太不合适了,一个列表页面下来,20多MB没有了。页面显示肯定会很慢。


解决思路

我们一般的做法有:

1、在CMS中上传一个海报大图,再上传一个海报小图。

2、在CMS中上传一个海报大图,保存的时候,系统自动生成一个海报小图。

3、在CMS中上传一个海报大图,在网页请求图片的时候,附带需求图片的 width 和 height,程序自动判断需求图片是否存在,如果不存在则使用对应的大图生成一个图片响应到客户端。


上面三种做法,1、2 两种情况不够灵活,如果系统还有更多地方需要显示不同尺寸的这样的图片呢?或者系统二期、三期……扩展的时候也有可能有更多尺寸的图片需求呢?

至于第三种方法,相对比较灵活,只有在我们需要的时候才生成。


我们现在需要使用 Apache 来处理我们的静态图片资源。一般情况下 Apache 可不会去管你的图片存在不存在,当我们访问一个新的尺寸图片时,服务器上不存在图片文件,Apache 就直接响应404了。

现在我们要做的就是,让Apache 来判断文件是否存在,如果文件不存在就转而请求我们生成图片的请求。

这样以来,每个尺寸的图片,在需求的时候,第一次 Apache 会交给我们的程序去生成图片,以后这个图片存在了,就全部由Apache 自己管理了。


Apache 配置

下面来说一下 Apache 怎么配置,来实现 “当文件不存在的时候,转发请求到处理程序”。

1、开启 rewrite 模块

      去除httpd.conf文件中 #LoadModule rewrite_module modules/mod_rewrite.so 前面的"#"号

2、在 httpd.cnf 中增加配置(没有位置要求,一般我们放在文件最后即可)

      我是用的是 apache 2.4 的 VirtualHost ,图片处理程序是用的 Tomcat,所以也给Apache 添加了mod_jk 模块(这个本文不做讲解,可以查看帖子 http://blog.csdn.net/catoop/article/details/47974773)

      需要添加的配置内容为:

        <IfModule mod_rewrite.c>                RewriteEngine On
# '-s' (is regular file, with size)
# '-l' (is symbolic link)
# '-d' (is directory)
# 'ornext|OR' (or next condition)
# 'nocase|NC' (no case)
# 'last|L' (last rule)
# 'QSA' 追加请求字符串

RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-s
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-l
RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-f

#RewriteRule ^(.*)\.[jpg|png|bmp]$ %{HTTP_HOST}/createimage.jsp?path=%{REQUEST_URI} [NC,L]
#RewriteRule ^(.*)\.(jpg|png|bmp)$ createimage.jsp?path=%{REQUEST_URI} [NC,L]
RewriteRule ^(.*)\.(jpg|png|bmp)$ http://shanhyweb.example.com/createimage.jsp?path=%{REQUEST_URI} [NC,L]
#RewriteRule ^(.*)\.(jpg|png|bmp)$ /createimage.jsp?path=%{REQUEST_URI} [NC,L]

</IfModule>

      配置可以直接在 httpd.cnf 中添加,也可以在 VirtualHost  中配置,因为我使用的是 VirtualHost 所以我的配置是在 apache2/conf/extra/httpd-vhosts.conf 中,如下:

########################################################LoadModule jk_module modules/mod_jk.soInclude conf/mod_jk.conf########################################################<VirtualHost *:80>    #ServerAdmin webmaster@dummy-host.example.com    DocumentRoot "/svcroot/runtime/webstatic/shanhyweb"    ServerName shanhyweb.example.com    #ServerAlias www.shanhyweb.example.com    ErrorLog "logs/shanhyweb-error_log"    CustomLog "logs/shanhyweb-access_log" common        <IfModule mod_jk.c>                #日志输出文件(其他配置也可以重写mod_jk.conf里面的配置)                JkLogFile logs/mod_jk_shanhyweb.log                #指URL指向如果有servlet,则让worker_web去处理                JkMount /servlet/* worker_web                #指URL为/*.jsp的页面,让worker_web去处理                JkMount /*.jsp worker_web                #指URL为/*.do的页面,让worker_web去处理                JkMount /*.do worker_web                #指URL为/*.json的页面,让worker_web去处理                JkMount /*.json worker_web        </IfModule><IfModule mod_rewrite.c>RewriteEngine On# '-s' (is regular file, with size) # '-l' (is symbolic link) # '-d' (is directory) # 'ornext|OR' (or next condition) # 'nocase|NC' (no case) # 'last|L' (last rule) # 'QSA' 追加请求字符串RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-s RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-l RewriteCond %{DOCUMENT_ROOT}%{REQUEST_FILENAME} !-fRewriteRule ^(.*)\.(jpg|png|bmp)$ http://shanhyweb.example.com/createimage.jsp?path=%{REQUEST_URI} [NC,L]</IfModule>        <Directory "/svcroot/runtime/webstatic/shanhyweb">                Options FollowSymLinks                AllowOverride None                Require all granted        </Directory></VirtualHost>

关于图片的处理,推荐大家可以去了解下 GraphicsMagick 处理图片的。


===========================================

利用这种方法,也可以做其他需求,比如网页的静态化:index.do 用来生成 index.html ,Apache 判断如果有HTML存在就直接响应给浏览器,如果不存在就转发到 index.do 处理生成 index.html 


注意:生成图片的这个处理,对同一个图片处理那段代码要做好加锁或同步处理,防止出现高并发情况下,读取和生成图片因为资源占用而出问题的情况。



------------------------------------

(完)