ShareList是一个网页版服务器目录浏览Web程序,它能够挂载本地目录、虚拟目录、OneDrive、Google Drive等文件系统,功能强大,还支持预览部分多媒体文件,如jpg、mp4、mkv等。
问题描述
这几天有人送我了一个Office365 E5
子账户,有免费的1TOneDrive网盘
,所以我就共享了个目录挂载到我的ShareList
上,但是却报错了,步骤如下:
在OneDrive
中新建一个共享目录test
,里面放了一张图片。
ShareList
挂载OneDriveForBusiness
到显示名称为testme
的虚拟目录。
ShareList
首页显示:
点击进入testme
却报错了:
问题调查分析
根据调用栈可以清楚的看到,Onedrive
的分享由sharelist/plugins/drive.odb.js
插件提供支持,错误是Invalid time value
。
离format.js
最近的调用是113
行,所以看看代码到底是什么。
1
updated_at: datetime(i.Modified.replace(/\//g,'-')),
这段代码就是把i
的/
字符替换为-
,看上去并没有什么问题。但是错误是Invalid time value
,所以看看datetime()
传入的时间到底是什么。
我们在return {
前面插入console.log("i:", i)
。
1
2
3
4
5
6
7
8
9
10
11
12
13
let children = data ? data.map((i) => {
console.log("i:", i)
return {
id: rootId + '@' + i.FileRef,
name: i.FileLeafRef,
ext: i['.fileType'],
protocol: defaultProtocol,
created_at: '-',
updated_at: datetime(i.Modified.replace(/\//g,'-')),
size: i.FileSizeDisplay,
type: i.FSObjType == '1' ? 'folder' : undefined,
}
}) : []
然后用node
启动服务器,会打印出i
的所有值。(注:这里的i
其实是sharelist
请求Onedrive分享链接
返回的Header 头
)。
1
2
3
4
5
6
7
i: { ID: '9',
...
Modified: '19/1/2020 下午 2:20',
'Modified.': '2020-01-19 14:20:56',
'Modified.FriendlyDisplay': '1|0|6|2',
...
'.etag': '"{DB2F9350-4B23-44DE-863B-C3C0DF7A2E0E},4"' }
最主要的就是Modified
了,它的值是19/1/2020 下午 2:20
,看上去没有什么问题。那么现在看看报错核心文件sharelist/app/utils/format.js
的30
行是什么。
1
return a.toISOString()
再看看这里的a
是什么。
1
2
3
4
5
6
7
8
9
10
11
12
const datetime = (date, expr = 'iso') => {
var a = new Date()
if(isDate(date)){
a = date
}
else if(isString(date)){
try{
a = new Date(date);
}catch(e){
}
}
很明显,drive.odb.js
调用datetime()
时传入了19-1-2020 下午 2:20
这个日期(/
被replace()
替换成了-
),那么具体执行的是a = date
还是a = new Date(date)
呢?
追一追代码,发现核心代码在sharelist/app/utils/base.js
,如下:
1
2
3
const isType = (type) => (obj) => (Object.prototype.toString.call(obj) === `[object ${type}]`)
...
const isDate = isType('Date')
很明显,我们这里调用的是[object String]
,而不是[object Date]
,那么isType(date)
会为false
,因此会执行a = new Date(date);
,那么我们在Chrome浏览器的Console
执行一下看看。
1
2
a = new Date('19-1-2020 下午 2:20')
Invalid Date
原因就在这里了,日期格式错了。那么我们再来看看返回的Header 头
,发现还有一个'Modified.'
,一看就是标准格式,那么我们用它试试看。
1
2
a = new Date('2020-01-19 14:20:56')
Sun Jan 19 2020 14:20:56 GMT+0800 (China Standard Time)
解决方法
问题就调查清楚了,ShareList
的sharelist/plugins/drive.odb.js
文件中updated_at: datetime(i.Modified.replace(/\//g,'-')),
使用了错误的Modified
头属性,把它替换成'Modified.'
即可,注意这里由于属性名包含.
字符,所以我们用数组方式调用。
1
updated_at: datetime(i['Modified.'].replace(/\//g,'-')),
现在再看看ShareList
的testme
目录,大功告成。
额外注意事项
在调试过程中,我发现后台建立虚拟目录时不能使用部分关键字,如od
、onedrive
等,不然会被解析成相应插件打开目录导致错误,具体的如下:
1
2
3
4
5
6
7
8
9
10
11
12
13
liuxu:~/source/git/sharelist/plugins$ find . -name "*.js" | xargs grep "protocols ="
./drive.od.api.js:const protocols = ['oda']
./drive.h5ai.js:const protocols = ['h5ai']
./drive.book.js:const protocols = ['book']
./drive.od.js:const protocols = ['od', 'onedrive']
./drive.lanzou.js:const protocols = ['lanzou']
./drive.odb.js:const protocols = ['odb']
./drive.openload.js:const protocols = ['openload']
./drive.gd.api.js:const protocols = ['gda']
./drive.gd.js:const protocols = ['gd','googledrive']
./drive.webdav.js:const protocols = ['webdav']
./drive.github.js:const protocols = ['github']
./drive.joy.js:const protocols = ['joy']
所以取名最好用大写或者带_
的字符串或者中文。