FODI,Fast OneDrive Index 的缩写,意为 OneDrive 快速列表,是一款 OneDrive 列表程序。相较于其他程序,此版列表速度极快,且无需服务器,部署极为简单,当然,UI就不那么好看了。
这个教程还是利用Cloudflare Workers部署FODI,无需服务器,但是需要一个OneDrive。前面提过了如何利用cf workers搭建Google Drive,文章如下:
[mark_b]
GoIndex搭建Google Drive目录索引网盘的真香教程
[/mark_b]
1、前言
github:https://github.com/vcheckzen/FODI
功能:
- 接近秒速列表
- 指定展示路径
- 特定文件夹加密
- 无需服务器免费部署
- 基本文本、图片、音视频和 Office 三件套预览
缺点:
- 功能简单,界面简陋
- 不支持巨硬家的 IE 和 UWP 版 EDGE 浏览器
- 可能不支持包含千级数量以上文件的文件夹展示
2、创建 Workers
如果你没有cloudflare的账号的话,需要注册一个,注册就不多说了。登录之后会进入主页,点击靠近右下角的 Workers
。
此时系统会建议你修改子域名,直接点击 Set up
,随后点击弹出对话框中的 Confirm
,之后会进入套餐选择页面,选择免费即可,找到 Continue with free
,如图。
这样就创建好了一个workers。
3、上传 FODI 后端
现在进入到workers的工作台,进入到代码编辑页面,复制如下代码到左侧的代码框中。[reply]
/** * IS_CN: 如果为世纪互联版本,请将 0 改为 1 * EXPOSE_PATH:暴露路径,如全盘展示请留空,否则按 '/媒体/音乐' 的格式填写 * ONEDRIVE_REFRESHTOKEN: refresh_token */ const IS_CN = 0; const EXPOSE_PATH = "" const ONEDRIVE_REFRESHTOKEN = "" async function handleRequest(request) { let requestPath let querySplited let queryString = request.url.split('?')[1] if (queryString) { querySplited = queryString.split('=') } if (querySplited && querySplited[0] === 'file') { const file = querySplited[1] const fileName = file.split('/').pop(); requestPath = file.replace('/' + fileName, '') const url = await fetchFiles(requestPath, fileName) return Response.redirect(url, 302) } else { const { headers } = request const contentType = headers.get('content-type') let body={} if (contentType && contentType.includes('form')) { const formData = await request.formData() for (let entry of formData.entries()) { body[entry[0]] = entry[1] } } requestPath = body ? body['?path'] : ''; const files = await fetchFiles(requestPath, null, body.passwd); return new Response(files, { headers: { 'content-type': 'application/json; charset=utf-8', 'Access-Control-Allow-Origin': '*' } }) } } addEventListener('fetch', event => { return event.respondWith(handleRequest(event.request)) }) const clientId = [ '4da3e7f2-bf6d-467c-aaf0-578078f0bf7c', '04c3ca0b-8d07-4773-85ad-98b037d25631' ] const clientSecret = [ '7/+ykq2xkfx:.DWjacuIRojIaaWL0QI6', 'h8@B7kFVOmj0+8HKBWeNTgl@pU/z4yLB' ] const oauthHost = [ 'https://login.microsoftonline.com', 'https://login.partner.microsoftonline.cn' ] const apiHost = [ 'https://graph.microsoft.com', 'https://microsoftgraph.chinacloudapi.cn' ] const OAUTH = { 'redirectUri': 'https://scfonedrive.github.io', 'refreshToken': ONEDRIVE_REFRESHTOKEN, 'clientId': clientId[IS_CN], 'clientSecret': clientSecret[IS_CN], 'oauthUrl': oauthHost[IS_CN] + '/common/oauth2/v2.0/', 'apiUrl': apiHost[IS_CN] + '/v1.0/me/drive/root', 'scope': apiHost[IS_CN] + '/Files.ReadWrite.All offline_access' } async function gatherResponse(response) { const { headers } = response const contentType = headers.get('content-type') if (contentType.includes('application/json')) { return await response.json() } else if (contentType.includes('application/text')) { return await response.text() } else if (contentType.includes('text/html')) { return await response.text() } else { return await response.text() } } async function getContent(url) { const response = await fetch(url) const result = await gatherResponse(response) return result } async function getContentWithHeaders(url, headers) { const response = await fetch(url, { headers: headers }) const result = await gatherResponse(response) return result } async function fetchFormData(url, data) { const formdata = new FormData(); for (const key in data) { if (data.hasOwnProperty(key)) { formdata.append(key, data[key]) } } const requestOptions = { method: 'POST', body: formdata }; const response = await fetch(url, requestOptions) const result = await gatherResponse(response) return result } async function fetchAccessToken() { url = OAUTH['oauthUrl'] + 'token' data = { 'client_id': OAUTH['clientId'], 'client_secret': OAUTH['clientSecret'], 'grant_type': 'refresh_token', 'requested_token_use': 'on_behalf_of', 'refresh_token': OAUTH['refreshToken'] } const result = await fetchFormData(url, data) return result.access_token } async function fetchFiles(path, fileName, passwd) { if (!path || path === '/') { if (EXPOSE_PATH === '') { path = '' } else { path = ':' + EXPOSE_PATH } } else { if (EXPOSE_PATH === '') { path = ':' + path } else { path = ':' + EXPOSE_PATH + path } } const accessToken = await fetchAccessToken() const uri = OAUTH.apiUrl + encodeURI(path) + '?expand=children(select=name,size,parentReference,lastModifiedDateTime,@microsoft.graph.downloadUrl)' const body = await getContentWithHeaders(uri, { Authorization: 'Bearer ' + accessToken }) if (fileName) { let thisFile = null body.children.forEach(file => { if (file.name === decodeURIComponent(fileName)) { thisFile = file['@microsoft.graph.downloadUrl'] return } }) return thisFile } else { let files = [] let encrypted = false for (let i = 0; i < body.children.length; i++) { const file = body.children[i] if (file.name === '.password') { const PASSWD = await getContent(file['@microsoft.graph.downloadUrl']) if (PASSWD !== passwd) { encrypted = true; break } else { continue } } files.push({ name: file.name, size: file.size, time: file.lastModifiedDateTime, url: file['@microsoft.graph.downloadUrl'] }) } let parent if (body.children.length) { parent = body.children[0].parentReference.path } else { parent = body.parentReference.path } parent = parent.split(':').pop().replace(EXPOSE_PATH, '') || '/' parent = decodeURIComponent(parent) if (encrypted) { return JSON.stringify({ parent: parent, files: [], encrypted: true }) } else { return JSON.stringify({ parent: parent, files: files }) } } }
[/reply]
不会放,看截图:
注意:
- IS_CN: 如果为世纪互联版本,请将 0 改为 1
- EXPOSE_PATH:暴露路径,如全盘展示请留空,否则按 ‘/媒体/音乐’ 的格式填写
- ONEDRIVE_REFRESHTOKEN: refresh_token
- 至于如何获取refresh_token 看下面的获取方法。
- 预览看到类似图片左侧的数据显示,表示安装成功,之后,我们设置 一个前端,即可展示列表了。如何设置前端,依然要接着往下看。
4、获取 refresh_token
进入 ( 该网址)点击其中的 Get a refresh_token
,在打开的微软账号登录页面中,填写你的 OneDrive 账号和密码
,完成登录。
登录完毕后浏览器将跳转回上面的页面,此时修改网址,从左往右找到第一个 ?
,将其 删除
。再找到第一个 &
,将其改为 ?
,注意要使用英文输入法。下面是修改前后的网址对比:
https://.../?authorization_code&code=... https://.../authorization_code?code=...
修改完毕后直接回车,稍等片刻页面将返回 refresh_token
,复制到代码的“refresh_token”中。
5、通过 Github Pages 部署前端
前端仅是一个 HTML 文件,可放到任意静态服务器,此处通过 Github Pages 部署,部署完成后可通过 username.github.io
打开你的网盘。
注册并登录 Github,随后打开 该仓库,点击靠近右上角的 Fork
。
稍等片刻,打开“front-end”中的 index.html
。然后点击靠近 右上角
的 铅笔
按钮,编辑该文件。如图:
注意:
- SCF_GATEWAY:这里填写你cf workers的分配地址。
- SITE_NAME:站点名称随便填写。
看图:
填写完毕后点击靠近页面最下方的 Commit changes
点击靠近页面右上角的 Settings
,将 Repository name
改成 你的 Github 用户名.github.io
,随后点击 Rename
。
下拉该页面,找到 Github Pages
,将 Source
下拉框的值改成 master branch
,如果没有则无需修改。
现在,就可以通过 你的 Github 用户名.github.io
访问网盘了。
6、宝塔设置前端
如果你有自己的服务器,可以在安装宝塔面板之后,新建网站,绑定好域名。然后下载程序到自己的网站根目录。
解压之后把“FODI-master/front-end”下面的“index.html”文件,拷贝到网站根目录,之后打开编辑,和第5的方法一样,如下:
保存,即可打开访问,效果如图:
7、最后
虽然界面简陋,但是功能还不错,打开速度快。支持基本文本、图片、音视频和 Office 三件套预览。可能不支持包含千级数量以上文件的文件夹展示,不支持巨硬家的 IE 和 UWP 版 EDGE 浏览器!
推荐在自己的服务器上部署前端,就是一个网页而已,绝对轻量级了。很多人不知道怎么获取 token,可以通过下面URL登录。
国际版, 个人版(家庭版)
https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=78d4dc35-7e46-42c6-9023-2d39314433a5&response_type=code&redirect_uri=http://localhost/onedrive-login&response_mode=query&scope=offline_access%20User.Read%20Files.ReadWrite.All
中国版(世纪互联)
https://login.chinacloudapi.cn/common/oauth2/v2.0/authorize?client_id=dfe36e60-6133-48cf-869f-4d15b8354769&response_type=code&redirect_uri=http://localhost/onedrive-login&response_mode=query&scope=offline_access%20User.Read%20Files.ReadWrite.All