今天想给大家分享一款图床应用和一个对应的Typecho插件,主要作用是将博客的图片存储功能放到其它服务器上,以便于应对一些小水管主机的图片加载速度优化或者一些博主使用虚拟主机空间和流量较小的情况。

兔子君这个博客目前就是架设在一个虚拟主机上的,当初这个虚拟主机的作用主要是用于停泊域名用于网站备案而开通的,容量和流量都比较小。但是秉承着不要浪费的原则,其实也是想要在网上开辟一个属于自己的空间吧,所以就在这个虚拟主机上架设了这个博客,程序选用了轻量级的Typecho,但也因为是轻量级,所以整个bolg也只有一些基本功能,及其简约,很多都是需要靠插件来拓展。

博客程序架设好之后就发现了一个问题,如果图片访问量较大的情况下加载会比较慢,而且如果后续要经常发布带图内容,流量也容易出现不足的情况。因此这段时间就在网上尝试寻找一些解决方案,目的就是把图片存储到我腾讯云的主机上,过程中就发现了总体风评都比较好的LskyPro图床(兰空图床)程序,这是一个国产的开发的mysql+php的开源图床程序,目前已经是开发到V2.0.4。这个图床的部署安装都比较方便,接口也比较丰富而且有完善的描述,所以最终就选择了这个图床程序来作为博客的图床。官网和下载地址如下:
Lsky pro兰空图床官网
github下载地址

在腾讯云上部署好了兰空图床后,就开始寻找一个typecho的图床插件。发现了莫名开发的lksy适配typecho的插件,但是莫名开发的这款只适配lskyV1.64,适配不了最新的LskyPro V2版本。然后在莫名博客的评论区发现了由冷寂基于莫名V1版本修改出来的V2版本,支持适配LskyProV2版本。果断下载来使用,冷寂的博客地址和兰空V2的typecho插件下载地址如下:
冷寂的博客 Cold ' bolg
LskyProV2插件下载地址

偷偷告诉大家,这位大神还提供了自己的图床空间供大家可以免费使用,亲们如果没有打算自己搭建图床服务器,也可以使用冷寂的Cold 图床,真的非常贴心哈哈。

但在安装完成插件之后,兔子君发现了插件有一个bug,上传图片后在TypeCho的文件标题是[随机字符串.jpg]这样的格式,显然是不利于管理和识别,我就把图片标题和描述修改了,但是发现修改标题之后图片不显示,原本以为是插件和PHP8不兼容。尝试降级到PHP7.3还是发现同样的问题。尝试多次之后,发现只要修改的文件标题不带图片原本的后缀名,就会无法显示出来。如下图:
上传图片后修改标题导致图片不显示
仔细阅读插件的代码之后,发现插件是以文件的标题title字段去读取图片的扩展名,如果是是允许的类型图片才能正常显示,插件原始代码如下:(大约在117-128行附近)

public static function attachmentHandle(array $content): string
{
    $arr = unserialize($content['text']);
    $ext = self::_getSafeName($content['title']);
    if (self::_isImage($ext)) {

        return $content['attachment']->path ?? '';
    }

    $ret = explode(self::UPLOAD_DIR, $arr['path']);
    return Typecho_Common::url(self::UPLOAD_DIR . $ret[1], Helper::options()->siteUrl);
}

可以看到变量$ext是读取了数据库中['title']的值,然后再去判断它的后缀名是否为图片,找到原因之后,要来修复这个Bug就简单许多了,我将代码改写为读取数据表中的['text']字段(也就是typecho记录附件信息的字段),在字符串中查找图片地址部分并截取了.后面的3个字符作为图片的扩展名重新赋值给$ext,解决了这个问题。修改后的代码如下:

    public static function attachmentHandle(array $content): string
{
    $arr = unserialize($content['text']);
    /*在text字段中截取“.”后的3个字符作为文件扩展名*/
    $text = strstr($content['text'],'.');
    $ext = substr($text,1,3);
    if (self::_isImage($ext)) {

        return $content['attachment']->path ?? '';
    }

    $ret = explode(self::UPLOAD_DIR, $arr['path']);
    return Typecho_Common::url(self::UPLOAD_DIR . @$ret[1], Helper::options()->siteUrl);
}

做出了以上修改后,bug成功去除,可以随意修改上传后的文件标题了,但随即就发现了新的问题,当在typecho文件管理中删除图片,lskypro上并没有同步删除,而且在PHP8环境中还会出现警告。发现其删除代码也是一样使用了title作为判断文件的后缀名的方式。原始删除代码如下:(约79-89行)

public static function deleteHandle(array $content): bool
{

    $ext = self::_getSafeName($content['title']);
    if (self::_isImage($ext)) {

        return self::_deleteImg($content);
    }

    return unlink($content['attachment']->path);
}

解决思路如下,因为图床上传图片后会返回文件类型并存储在['attachment']中,因此我们只要把

$ext = self::_getSafeName($content['title']);

替换为:

$ext = $content['attachment']->type;//读取文件扩展名

即可完美解决这个问题,重新实现修改完文件标题后在typecho中删除附件能够正常的在lskypro中同步删除。

然后我也顺手将上传图片的代码修改了一下文件的重命名方式,兰空图床在上传时已经是做了重命名的操作。但这个typecho插件在上传时还会再次对文件标题进行一次随机重写,导致在LskyPro上显示的原始文件名也和本地的原始文件名不同,而且上传图片后返回的文件名是以lskypro的真实文件名作为typocho的标题。总之就是“本地电脑上的文件名”上传后返回到“typecho后台的文件名”和laskype后台显示的原始文件名都无法一一对应,导致看起来非常乱。如图:插件的随机文件名.png
所以我也就重写了上传文件时的重命名方式,使上传后图床上的原始图片文件名能够和本地图片文件名对应,并返回到typecho中。
正常保存原始标题.png
因为这个修改的代码比较零散,同时也修复了一些PHP8兼容性的问题,本君也就不一一列举修改方式了,我也将修改后的插件放到附件中分享出来,有需要的小伙伴可以下载去看看,使用中有遇到什么问题bug也可以来评论反馈。

以下地址可下载修改后的插件
修复后的LskyProV2插件.zip
优化日志:
2022-07-12修复原插件修改文件标题(主要是标题中的扩展名)导致图片不显示的问题;
2022-07-14优化上传保留文件原始文件名,修复了更改文件标题后无法同步删除图床原图片问题;
优化PHP8.0以上环境插件导致部分页面报警问题

最后感谢一下LskyPro程序作者wisp-x
Lskypro图床插件原作莫名
LskyproV2版插件作者冷寂

标签: 兰空图床, TypeCho插件, PHP

添加新评论