昨晚收到留言说那个缩略图插件无法下载,然后测试看了下,居然原来的附件都无法下载了,研究了下,终于发现问题所在。
先说一下Typecho附件的数据库设计:
通过查看TE的源码发现,TE的附件信息是以以下方式存放在contents表中的:
var/Widget/Upload.php 文件目录
/* /var/Widget/Upload.php line:120 */ $result = array( 'name' => $file['name'], 'path' => self::UPLOAD_PATH . '/' . $date->year .'/'. $date->month . '/' . $fileName, 'size' => $file['size'], 'type' => $ext, 'mime' => Typecho_Common::mimeContentType($path) ); /* ..... ...... */ /* /var/Widget/Upload.php line:258 */ $struct = array( 'title' => $result['name'], 'slug' => $result['name'], 'type' => 'attachment', 'status' => 'publish', 'text' => serialize($result), 'allowComment' => 1, 'allowPing' => 0, 'allowFeed' => 1 );
其中 $struct['text'] 返回的是序列化的附件信息字符串,其结构如下:
return "a:5:{s:4:"name";s:18:"Thumbnail-show.zip";s:4:"path";s:37:"/assets/attachment/2012/01/4f01d62cb3bfc.zip";s:4:"size";i:8513;s:4:"type";s:3:"zip";s:4:"mime";s:15:"application/zip";}";
此字符串的结构为 "数据类型":"长度":"值" 。注:integer和double直接返回 "数据类型":"值" 。https://mrasong.com/a/serialize-and-unserialize 关于更多的 serialize 和 unserialize 请参考官方说明。
现在返回正题,TE本身设计时,上传的附件是按 YYYY/mm/ 文件夹存放的,因为个人觉得没什么附件上传,所以就把 /var/Widget/Upload.php 文件中的存放路径修改为 YYYYmm/ 直接以月份存放,数据库中原来所有的 YYYY/mm/ 路径全部改为 YYYYmm/ ,ftp上附件也迁移了。
理论上,这样是好了,对,是好了,因为新上传的文件没有任何问题,通过 http://host/usr/files/YYYYmm/xxxxxx.xxx 可以直接下载,原来上传的附件也可以通绝对路径下载,但是...
问题还是出现了,我用 Attachment 插件,无法下载。原来的附件,在附件管理中,路径全为 http://mrasong.com 。
问题就出在上面介绍的 serialize 上,serialize 返回的数据中有一个长度,也就是说,改过数据库中附件的 path 但是没有改 path 字符串的长度。
将 s:38:"/usr/files/201201/4f01d62cb3bfc.zip" 改为 s:37:"/usr/files/201201/4f01d62cb3bfc.zip"
因为少了一个 "/" 字符串的长度少了1,到此,问题终于解决了。
总结:
Typecho确实写得非常好,通过研究TE的源码,自己也学了不少。顺便感谢下 Mr.Jiang 同学的提醒。
使用typecho上传附件时,插入远程图片是没问题的,但本地图片会报上传失败.
博客是搭建在腾讯服务器上的,Typecho会对服务器进行监测,如果不在BAE、SAE、ACE下,则不允许文件上传.
因此,可以去掉这一段监测代码.
[1] - 编辑 var/Typecho/Common.php
文件,修改如下代码:
修改前:
public static function isAppEngine()
{
return !empty($_SERVER['HTTP_APPNAME']) // SAE
|| !!getenv('HTTP_BAE_ENV_APPID') // BAE
|| !!getenv('SERVER_SOFTWARE') // BAE 3.0
|| (ini_get('acl.app_id') && class_exists('Alibaba')) // ACE
|| (isset($_SERVER['SERVER_SOFTWARE']) && strpos($_SERVER['SERVER_SOFTWARE'],'Google App Engine') !== false) // GAE;
}
修改后为:
public static function isAppEngine()
{
return false;
}
[2] - 修改上传文件夹 usr/uploads/
的权限:
sudo chmod -R 777 /path/to/blog/usr/uploads
至此,即可上传本地图片.
修改php.ini
文件.
注意修改PHP下的php.ini文件是无效的,要修改fpm下的php.ini文件
[1] - 使用 locate 找到所有php.ini
locate php.ini
[2] - 找到 fpm 目录下的php.ini
我的路径是/etc/php/7.0/fpm/php.ini
sudo vim /etc/php/7.0/fpm/php.ini
[3] - 修改下面三项
upload_max_filesize = 1000M;
post_max_size = 1000M;
max_execution_time=600;
[4] - 重新加载php-fpm服务
sudo service php7.0-fpm reload