误解Mac文件系统
网站改版之后,全是使用Markdown格式编写文章,所以图片、文章的链接自然也都是手动编码校验,配合VSCode的Mackdown插件,在Markdown中插入图片时左侧会显示图片的缩略图,以此来确认图片链接是否正确。然后再build出HTML传送到服务器,一直这么用也没有注意到一个严重的大小写敏感的问题。
直到最近,偶然发现自己的某一篇文章里的图片不显示,检查发现竟然是404。
本博客所有文章都是我一个字一个字敲出来了,并且所有的图片都是在本地,我每次都是检查插图没问题之后才发布的,怎么可能会有图片404的情况存在呢?而且,那篇文章所有的图片都不能显示,但是到服务器的部署目录下,确认图片文件是存在的。
排除了文件可能不能被Nginx读权限的原因之后,终于想到了一个可能性:会不会是大小写敏感问题?
我一直清楚的知道Linux操作系统的文件系统是大小写敏感的Case-Sensitive
,什么意思呢?就是在Linux下qttc
和QTTC
是两个不同的文件,我一直错误的误以为Mac的操作系统的文件系统也是大小写敏感的,实际上Mac操作系统的文件系统是不大小写敏感的Case-Insensitive
。所以在Mac操作系统下qttc
和QTTC
是同一个文件。
而404这个问题正好是图片文件名的大小写我疏忽大小写写错了,如VMware.jpg
被我写成VMWare.jpg
,而我不容易发现这个问题是因为在Mac电脑上VSCode编辑器里可以正常显示该图片,导致我误以为我的图片地址是没问题的,实际上发布到Linux服务器之后图片VMWare.jpg
就请求不到了
> GET https://www.qttc.net/VMWare.jpg
< http/1.1 404 Not found
> GET https://www.qttc.net/VMware.jpg
< http/1.1 200 Ok
解决问题
我的文章是一堆Markdown文件,使用NPM构建的项目,所以我立刻想到使用NodeJS的API来检查所有的历史文章,查出所有大小心不敏感的链接字符串
首先我要读到所有Markdown文件,然后挨个正则匹配出所有的链接字符串,读目录文件和文件内容可以利用这两个NodeJS API
- fs.readdirSync(dir_path)
- fs.readFileSync(file_path, 'utf-8')
读到所有文件内容之后,需要使用正则匹配出所有链接字符串
const regex = /[\!]?\[.*\]\(((https|http):\/\/www\.qttc\.net)?([\w\/\.\-]+)\)/gm;
const str = fs.readFileSync(markdown_file, 'utf-8');
let m;
while ((m = regex.exec(str)) !== null) {
if (m.index === regex.lastIndex) {
regex.lastIndex++;
}
let link = m[m.length - 1];
console.log(link); // 所有匹配到的链接地址
}
下一步,就是要判断一下链接地址是否存在于系统磁盘之中,这里要切记不可使用NodeJS的fs.existsSync(path)
方法,因为这个方法的底层还是操作系统的,所以以下情况是存在的
fs.existsSync('qttc'); // true
fs.existsSync('QTTC'); // true
这种情况下,只能自己写检测API,按照大小写敏感的思路去处理,核心如下
const is_exists_sync = (path) => {
const fs = require('fs');
const arr = path.split('/');
const filename = arr.pop();
const file_list = fs.readdirSync(arr.join('/'));
return file_list.includes(filename);
};
is_exists_sync('VMware.jpg'); // true
is_exists_sync('VMWare.jpg'); // false
以上例子表示,我有一个链接的地址写成了VMWare.jpg
,但实际的文件名为VMware.jpg
,我们先把图片目录下的所有文件名都读入一个数组,通过字符串比对的方式判断文件是否存在从而修复这个链接大小写不匹配的问题。
通过这个思路,我写出了检测脚本一共检查出大概十多处大小不敏感的链接,否则靠肉眼检查大小写敏感的链接字符串眼睛预计要看瞎了~~