开源图床 ImageX 介绍

前言

计划了大半年的图床改造计划终于告一段落,写篇文章简单记录下。

背景

在奶油葡萄运行了大半年后的某一天,我整理了下站点的占用空间,发现图片的数量和体积远比种子资源还大,而且增长速度也远超过种子。寻思着这样持续下去可能过不了多久,就得升级 VPS,掐指一算升级后的成本,觉得不太可以接受。

于是就开了个 Godaddy 的无限存储空间的虚拟主机(大概 80 人民币一年),用了一个开源图床(CF Image Host)专门用来存储图片。每隔一年左右,在 Godaddy 上重新开一个主机,数据迁移过去继续服务。

后面图片越来越多,每次在垃圾主机间迁移都感觉相当费劲,恰好 Vultr 送了个永久免费的 50GB 大容量存储的机会,就索性把图床迁移到了 Vultr。迁移没多久就换了个域名,从原来的 ituku.tk 换到了 i.endpot.com,主要是 .tk 域名忘记去续约了,域名要再次使用的话,需要付费而且价格昂贵,要不起要不起。

前几个月的某一天,突然闲下心来查看图床的使用情况,被日渐增长的图片数量和占用空间吓到了。当然主要还是贫穷限制了我的想象力,为了尽可能地压缩图床运营成本(毕竟是一个纯赔钱的买卖),我动起了改造图床的脑筋。

贫穷的智慧

BackBlaze B2 Storage

图床的运营成本主要来自两方面,一个是图片的存储费用,一个是图床的流量费用。现在的 VPS 动不动就有 500GB 或者 1TB 以上的免费流量,再在 VPS 前加个免费的 CDN(比如 CloudFlare),基本上流量费用可以忽略不计,那么问题主要就是图片的存储费用了。

之前有考虑到把图片全部存储到个人百度网盘上(有 2TB 免费空间),但是考虑到国内各个网盘都 GG 了,百度网盘将来哪一天也不让用了,岂不是很尴尬,所以这条路我认为行不通。

坚信「天下没有免费的午餐」的我,还相信「总该有便宜的午餐吧」。看着国内各种高价的云存储,再看看国外稍微低价的(亚马逊 / 谷歌 / 微软),总是觉得难已下手。

众里寻他千百度,终于找到了一家比较靠(pian)谱(yi)的厂商 BackBlaze。这是一家号称以友商 1/4 价格提供 100% 服务的老牌厂商,而且前 10GB 存储免费。大概盘算了下,如果有 50GB 的图片要存储,一年下来也才 3 美元。

图床瘦身

原用的图床程序每次上传的时候,都会存若干不同尺寸的缩略图。尽管每张缩略图的体积都不大,但是积少成多,随着图片数量的增长,最终占用的空间也是不容忽视的。所以在规划新版图床功能的时候,我毅然决定把缩略图这个功能割了。

根据奶油葡萄的用户使用情况,以及对已上传图片的扫描分析情况来看,很多用户会重复上传同一张图片,而原有图床程序基本上照单全收,这简直不能忍啊!所以,新版图床要有重复检查机制,对于相同图片,仅保留第一张图片即可。

图床设计

图床框架选型

我选用了世界上最好的语言 PHP + 世界上最好的框架 Laravel 来实现我的图床,不为什么,就因为我想拥有世界上最好的(嗯,真无耻)。图床的前端基于 Bootstrap 和 Bootstrap File Input,并借鉴了 sm.ms 的外观设计。

实现思路

图床的实现本身不具备多少难度,关键在于要兼容旧数据。所以我花了有近两周的时间去设计新的数据表,尽可能地兼容旧表的字段。

每张图片上传时,会生成两个唯一的 CODE,一个用于访问图片,一个用于删除图片,然后会将图片推送到 B2 云存储空间中。

每张图片都会计算一个 hash 值保存在数据表中,用于重复判断。新上传的图片的 hash 值若与之前的图片一样,仅是在数据表中插入一条记录,并记录两者的关联关系,并不会产生新的文件。

每张图片被访问时,如果图床本地有相应图片,则返回给用户,否则先从 B2 取回图片,再返回给用户。每次图片被访问时,会更新数据表中的访问时间戳字段,后台定时任务会根据该字段定时清理冷门的图片缓存。

Show Me Your Code

目前图片代码托管于 GitHub,有兴趣可以戳 endpot/ImageX 或者 HunterXuan/ImageX,我也提供了一个 Docker 版本,有兴趣戳 hunterxuan/imagex-docker