之前的博客中有提到基于apache2的模块开发,提供了下载文件的demo。但后来发现不仅仅是文件(准确说是图片)下载,还需要根据相关参数,提供图片缩略图下载、裁剪图下载或原图下载等功能。
一、编译问题:
种种原因,选用cximage库来提供图片处理功能。但坑爹的是这个库是C++的,而apache是c的,apxs怎么才能编译C++代码呢? 当然可以把cximage封装一下,提供一个C接口的库。但本人比较懒,还是希望直接将cximage编译到apache2模块中。主要解决步骤如下:
1、 模块代码中包含cximage的头文件、直接定义cximage类对象,以C++方式调用相关接口。
2、 代码编写完成后通过apxs编译。
#apxs编译代码的命令中需要指定c++头文件,并通过-S参数将gcc替换成g++
/usr/local/apache2/bin/apxs -L /usr/include/c++/ -L /usr/include/c++/3.4.6/x86_64-redhat-linux/ -i -c -a -S CC=g++ mod_api.c
libCxImage.a(ximatran.o): relocation R_X86_64_32S against `.rodata' can not be used when making a shared object; recompile with -fPIC
/home/apache-module/api/libCxImage.a: could not read symbols: Bad value
这应该不是一个普遍问题,主要是编译cximage时没有指定-fPIC,添加-fPIC选项重新编译cximage库,就可以了。
4、编译成功后,修改httpd.conf,加载mod_api.so,并设置handler.
实际上通过apxs编译的时候,应该会自动添加LoadModule的配置,但是 SetHandler还是需要自己手动加的。
<Location /api>
SetHandler api
</Location>
httpd: Syntax error on line 56 of /usr/local/apache2/conf/httpd.conf: Cannot load /usr/local/apache2/modules/mod_api.so into server: /usr/local/apache2/modules/mod_api.so: undefined symbol: jpeg_resync_to_restart
解决方法:应该是编译mod_api.so是缺少cximage相关的.a文件。用find cximage -name *.a 找出所有的.a文件,然后逐个添加到编译选项中测试,最终确定需要以下几个.a(顺序上被依赖的库放在后面,需要依赖别人的库放在前面):
-lCxImage -ljasper -lpng -ltiff -lzlib -ljpeg
所以最终的编译命令如下:
/usr/local/apache2/bin/apxs -L /usr/include/c++/ -L /usr/include/c++/3.4.6/x86_64-redhat-linux/ -i -c -a -S CC=g++ mod_api.c -L./lib -lCxImage -ljasper -lpng -ltiff -lzlib -ljpeg
PS:
另外网上还有说需要在httpd.conf的LoadModule之前加上一句LoadFile,已加载C++模块:
LoadFile /usr/lib64/libstdc++.so.6
LoadModule api_module modules/mod_api.so
但实际测试了一下,不加这句似乎也没有什么问题。
二、模块代码编写
概括的说,主要有三类需求:首先从调用我们内部的SDK从其他内部平台下载图片原始文件,然后根据参数
1) 返回原图;2)返回缩略图;3)裁剪指定范围的图片
这里忽略了调用sdk的步骤,假设图片就在服务器本地,且直接在url路径中表示本地路径,设计的url规则如下:
u