档案 File
我们可能会需要产生图片或档案供使用者去下载,这些让使用者可以公开存取档案的原则大概有这些:
- 随机档名
- 同一目录下不要有太多档案
- 资料库仅储存图片档名,不要纪录完整路径
- 使用 CDN 提高负载平衡及降低频宽成本
随机档名
很多人可能会图方便,让档案用可以猜出规则的方式做储存,例如有人可能在储存会员的照片,是用会员的编号当作图片档名,如果会员编号是整数的栏位,则就更容易让人家猜出来,更方便地去解析你主机的所有会员照片,像是:
100000001.png
100000002.png
100000003.png
...
100999999.png
所以通常我们会将图片的名称依照会员编号的规则去做加密,我们可能可以用 md5 去做加密的动作,这样图片档名可能会像是:
d69d3401d01a8ceed4549434e5ad9f40.png (`100000001` md5)
5a5ea04157ce4d020f65c3dd950f4fa3.png (`100000002` md5)
154666111ab87ce13405f384faeb5428.png (`100000003` md5)
...
e0b50eb5c4add211417977e1f79364e0.png (`100999999` md5)
这样图片的档名看起来随机了许多,比较不容易被猜出来,但是对比较厉害的人,可能会想要拿你的会员编号自己做 md5,所以还是可以看出规则,这时候我会试着在 md5 的会员编号字串加自定义的 salt 字串像是 KeJyun
,这样出来的图片档名会像这样:
a3bce35e2b4e57911869b1bf5d040d71.png (`100000001KeJyun` md5)
5121a0fabb52c26c01817ee65df683a8.png (`100000002KeJyun` md5)
2ec12af8e6e011a0f5256b61db2145c3.png (`100000003KeJyun` md5)
...
467bd65bf6d4864adcc633caf2a70f7d.png (`100999999KeJyun` md5)
这样除非对方知道我们使用哪一个 salt 去做加密,否则就很难被猜出来
同一目录下不要有太多档案
我们存放会员大头照的路径可能会像是: http://www.kejyun.com/users/images/a3bce35e2b4e57911869b1bf5d040d71.png
在上面的例子我们把所有的会员照片都存放在 users/images
的目录下,对于系统程式,我们可以很快的指定路径去读取该档案出来,但如果对于系统端的管理者,要去管理这些档案时就会造成很大的困扰,想像你有 1000 万个会员照片,所有的会员照片都放在同一个目录下面,光是要使用 ls
指令去列出那个目录的所有照片,对于系统来说就是一大梦靥…
所以我们通常会对档案做资料夹的分层处理,像是 a3bce35e2b4e57911869b1bf5d040d71.png
档案,我们可能取其前 3 个字元 a3b
去做资料夹的分层,所以我们图片会份在 users/images/a3b/a3bce35e2b4e57911869b1bf5d040d71.png
目录下,分层资料夹的 3 个字元的资料排列组合为 46,656
种,所以若我们有 1000 万
个会员照片,我们可以预期照片会被平均的放在到各个分层资料夹,每个分层资料夹约 214 张
照片 (10000000 / 46625 = 214.33)
,这样对于系统在做档案的索引及浏览也会比较快。
资料夹的分层要如何分层,完全取决于你系统专案资料数量的需求,若你预期你的档案会超过 1 亿种,那麽分层方式我们可能会分成 2 层,依照上面规则,照片可能会被放到 users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
下面,要怎麽分层处理完全取决于你的需求状况,没有一定的规则!
资料库仅储存图片档名,不要纪录完整路径
我们的档案可能会随着系统使用人数变多,需要转换成不同的管理方式,所以档案在做大型专案时,很有可能会随时被移动位置的,所以千万不要将完整的图片路径存到资料表栏位中,否则以后在做档案效能最佳化调校时,资料表档案路径还需要重新的异动更新,会是很大的难题,可能的瓶颈可能会卡在:
- 专案不能只为了调整图片路径而关站维护
- 资料量很大,更新档案路径很慢,可能需要 3~7 天以上去更新资料表的资料
- 若更新失败,或者是又需要重调整架构时,所耗费时间会更长
所以我们在资料表只要纪录档案的档名就好,所有与架构有关的资料通通由程式去控制产生,程式只要改一下,档案的存取架构随时都可以容易的做异动
使用 CDN 提高负载平衡及降低频宽成本
我们的主机可能会使用 AWS、Linode 之类的云端服务,这些的主机可能是放在日本或美国,我们希望使用者去距离使用者自己比较近的 CDN 主机,去存取这些不常被异动的静态资料,这样可以提高原本主机本身的负载流量,将流量做分散式的处理。
我们的图片可能放在像是这样的网址下:
http://cdn1.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn2.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
http://cdn3.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
...
http://cdn9.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
这些不同的主机存放的图片都与原主机的 http://www.kejyun.com/users/images/a3bc/e35/a3bce35e2b4e57911869b1bf5d040d71.png
相同,只是我们把同样的静态档案分流複製到各个 CDN 主机上,这样就不用让原主机承载过高的频宽吞吐量了!