在上一篇中介绍了ThumbCached的功能和使用方法,这篇主要介绍如何利用ThumbCached储存和优化相册网站中的缩略图。
为什么要用ThumbCached或者这类的程序来保存缩略图呢?
假如你正在做一个相册或带有相册功能的网站,相信第一个想到的问题是如何保存大量用户上传的照片文件。首先想到的可能是用一个大硬盘来解决咯,现在1TB的硬盘才1.5K左右,买3个做成RAID5,划分个目录出来保存所有的照片文件,问题就轻松解决了。假如过了几个月,你的网站莫名其妙地热起来,这三个硬盘的数据快爆了,这时候怎么办呢?再加3个硬盘,加到服务器机箱塞满硬盘为止,呵呵。如果所有硬盘都爆了,这时应该考虑使用分布式的文件系统(DFS)了,否则系统的扩展和数据的迁移会很头痛。DFS软件有很多可以选择,收费免费开源闭源的都有。好了,现在原始照片文件储存问题解决了,接下来看看缩略图的情况,一般相册都会对一张照片生成1个小尺寸的缩略图以供站内浏览,同时还会生成其他3、4个尺寸的小图以供到blog或论坛贴图,我们可以把这些网站产生的文件统统都存到DFS里。不过对于最小那个缩略图似乎可以优化一下,因为它们被高频率访问,同时它们很小(48*48像素的jpeg文件一般在2KB左右),大量这些文件会浪费部分磁盘空间。如果我们把这些小家伙用专门的一台服务器来装起来,并加个缓冲,再用一个轻量级的http服务程序来喷这些小数据,似乎是一个不错的优化策略。
ThumbCached本来的用途就像上段所述那样,被设计来做小缩略图的缓冲,以试图优化一些高访问率的网站(可惜的是这个组件所属的项目并没有预期的高访问量,做网站和做技术并不是一回事啊,呵呵,扯远了) ,要注意它不是文件系统,不能当成文件系统用哦。
当用户上传完照片之后,后台程序压缩并得到小缩略图,通过类似下面的代码保存到Thumbcached里。

/**//// <summary>
/// 保存缩略图,在用户上传完照片之后调用
/// </summary>
public void Save(long fileId, DateTime lastModifyTime, Stream stream)

{
//NOTE::stream为小缩略图文件的数据流

//实例化ThumbCached的客户端
TCClient thumbClient = new TCClient("tcd001");
thumbClient.Add(fileId, stream.ToArray(), lastModifyTime);
}
而在轻量级http服务程序里,读取Thumbcached里头的数据的代码大致如下:

/**//// <summary>
/// 向客户端浏览器传送缩略图
/// </summary>
/// <param name="fileId"></param>
public void Show(long fileId)

{
//NOTE::这里的Response应该是轻量级http服务程序中负责响应的对象。
//这里使用了asp.net的Response的风格是为了说明大概的步骤.
//下面的Request同样的意思。

Response.ClearContent();
Response.ContentType = "image/jpeg";

//判断日期
string lastModified = Request.Headers["If-Modified-Since"];
DateTime lm = DateTime.MinValue;
if (DateTime.TryParse(lastModified, out lm))

{
lm = lm.ToLocalTime();
}

//实例化ThumbCached的客户端
TCClient thumbClient = new TCClient("tcd001");
try

{
//尝试从缓存中获取缩略图,并返回至用户浏览器
string tbKey = fileName + "-" + sizeType;
ThumbBlock imgBlock = thumbClient.Get(tbKey, lm);
Response.AppendHeader("Last-Modified", imgBlock.LastModifyTime.ToUniversalTime().ToString("r"));
Response.BinaryWrite(imgBlock.Data);
}
catch (BlockNotFoundException)

{
Response.StatusCode = 404;
}
catch (BlockNotModifyException ex)

{
//被请求的内容在指定的时间之后没有发生改变
Response.AppendHeader("Last-Modified", ex.LastModifyTime.ToUniversalTime().ToString("r"));
Response.StatusCode = 304;
}
catch

{
Response.StatusCode = 500;
}

Response.End();
}
慢着,ThumbCached本身不是内置http服务吗?为什么不直接拿他对外喷图片数据,还需要再外加一层http服务呢,这是因为有时网站可能会有一些权限控制,将网站内部的数据完全暴露应该不是一个很好的做法。