山野莽夫

  • 归档
    • 随笔
    • 建站资源
    • 分享
    • 代码
  • 地球物理学
    • 专业课
    • 概念解释
  • 计算机
  • 互联网
  • 教程
  • 规划
  • 实验室
    • 珍藏的软件
    • 贴吧云签到
    • A1账号自助申请
山野莽夫
小学生的挣扎的点点滴滴
  1. 首页
  2. 互联网
  3. 正文

使用CloudFlare Workers 零成本部署 OneDrive 文件列表程序FODI(Fast OneDrive Index)

2020年2月20日 7386点热度 0人点赞 8条评论

2020506 谢谢评论大佬,更新一下世纪互联的问题。世纪互联需要专门的链接获取refresh_token。在下方更新。

这也是忽然而产生的一个想法。最近hk服务器到期,需要迁移自己以前搭建的olaindex和pyone。但是现实不是那么美好,自己已经没有闲置服务器可以用了,我也不想再购买新服务器,因为好多东西,瞎折腾也免不了吃灰的厄运。既花了钱,也没能够增强自己的技术。于是便想着有没有免费的方法。

其实还有Heroku这个工具可以部署onelist。但是我记得用cf可以部署goindex这种谷歌网盘的列表程序。虽然cf已经被玩坏了,cf搭建goindex已经没有速度了。但是onedrive国内可以直接访问,那么就不需要经过cf,应该可以保证一定的速度。那么是不是cf可以部署onedrive的列表程序呢?有了想法,立马去百度 and google 了一下,终于找到了一个程序FODI这个程序,是支持使用云函数部署的。

FODI( Fast OneDrive Index )

  • 接近秒速列表;
  • 指定展示路径;
  • 特定文件夹加密;
  • 无需服务器免费部署;
  • 基本文本、图片、音视频和 Office 三件套预览;

FODI 程序的开源地址如下:

https://github.com/vcheckzen/FODI

但是官网不知什么原因,作者并没有维护。那个部署步骤已经没办法看了。但是幸运的是,vircloud大佬已经写了一个教程,把基本步骤已经写明,于是,我参考大佬的教程,来造这个轮子。

一、获取refresh_token

国际版访问如下网址:

https://service-36wivxsc-1256127833.ap-hongkong.apigateway.myqcloud.com/release/scf_onedrive_filelistor

点击 Get a refresh_token ,然后使用你的office365账户登录

如果你是世纪互联(国内版onedrive)(比如同济大学的)请访问如下链接:

https://service-gzs9xkdm-1256127833.ap-hongkong.apigateway.myqcloud.com/release/onedrive-token-cn

登录完成后你发现又返回原来的界面。然后需要把地址栏的链接中

.../?authorization_code&code=... 为

.../authorization_code?code=... 并重新访问,修改完后如下。

复制返回的 refresh_token 存储下来。

二、cloudflare后台操作

1.进入cf workers后台,选择新建worker

2.复制如下代码,到worker编辑器中

/**
 * 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',
  [email protected][email protected]/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[[email protected]']
        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[[email protected]'])
        if (PASSWD !== passwd) {
          encrypted = true;
          break
        } else {
          continue
        }
      }
      files.push({
        name: file.name,
        size: file.size,
        time: file.lastModifiedDateTime,
        url: file[[email protected]']
      })
    }
    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 })
    }
  }
}

代码就是程序根目录中back-end-cf文件夹中的index.js(链接是文件Github地址)中的内容。然后把保存的 refresh_token 在指定位置修改,至于是不是世纪互联,和想展示哪个目录,请按程序注释修改。

保存生成

然后为如下界面

然后回到主界面

可以改称自己认为比较好的名,亦可以不改。记住这个域名。

三、部署程序主页

把引导页(位于front-end文件夹中的index.html)( 链接为文件的Github地址)部署到你的服务器上,当然也可以部署到Github Pages中,这儿可操作性太强了,我就不再描述了。然后需要修改文件中的SCF_GATEWAY。

这儿地址要加上https。

然后访问这个文件就可以,就可以看到这个页面了。这个页面是真的简洁,哈哈哈。没想到的简洁。打开要等几秒,才会显示内容。

几点小注意:(摘自vircloud.net)

  • 支持加密,在需加密的文件夹中新增 .password 文件,编码为 UTF8NoBOM ,内容为密码即可;
  • 后端实际上返回的是 json,所以前端其实是可以自己做一个的。
  • 内容传输时使用的地址是 OneDrive 官方地址,所以速度还是有保证的;
  • Worker 部署完是无法 GET 方式访问的,会提示“Error 1101 Worker threw exception”,不必理会;

标签: cf cf worker cloudflare CloudFlare Workers FODI onedrive
最后更新:2020年5月6日

小菜菜

菜鸟

打赏 点赞
< 上一篇
下一篇 >

文章评论

  • lisaooo

    发现同济的edu 获取不了refresh_token~

    2020年5月5日
    回复
    • 小菜菜

      @lisaooo 同济的账号应该没开api吧。另外同济的是不是世纪互联的啊。

      2020年5月5日
      回复
      • lisaooo

        @小菜菜 同济是世纪互联。
        成功了,要点世纪互联版token获取连接才行
        https://567899.xyz/fodi.html

        2020年5月6日
        回复
        • 小菜菜

          @lisaooo 同济的真香啊,还给开API

          2020年5月6日
          回复
          • lisaooo

            @小菜菜 试了下FODI感觉一般。还是退回用Zfile啦
            https://odrive.peter173.cf/

            2020年5月6日
          • 小菜菜

            @lisaooo 简洁到不可描述,要想使用还是需要有点前端知识,自己在开发下

            2020年5月6日
  • jacob

    把引导页(位于front-end文件夹中的index.html)( 链接为文件的Github地址)部署到你的服务器上,当然也可以部署到Github Pages中,这儿可操作性太强了,我就不再描述了。然后需要修改文件中的SCF_GATEWAY。
    这怎么操作

    2020年5月7日
    回复
    • 小菜菜

      @jacob 静态文件丢到随便一个服务器上就行了,我记得截图很清楚的

      2020年5月7日
      回复
  • razz evil exclaim smile redface biggrin eek confused idea lol mad twisted rolleyes wink cool arrow neutral cry mrgreen drooling persevering
    取消回复

    此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据。

    标签聚合
    ppt 地震学程序 wordpress 虚拟机 宝塔面板 c语言 模板 onedrive
    最新 热点 随机
    最新 热点 随机
    Azure Student 微软云 学生订阅 免费12个月用量避坑注意点集合 MP3音频文件格式详细解析 python按固定采样点个数分割wav格式音频 愉快使用谷歌免费人工智能平台colab,训练你的神经网络模型,为你的学术生活添砖加瓦 华为云版轻量应用服务器-云耀云服务器简单体验评测 Cloudflare 免费CDN自定义节点ip之自选cloudflare 高速节点ip工具分享
    计算方法实习实验报告-割线法 Azure Student 微软云 学生订阅 免费12个月用量避坑注意点集合 地震小科普之地震发生观点(成因) CentOS7minimal配置网络连接 大前端DUX1.3主题破解版分享 地震子波显示及合成地震记录

    COPYRIGHT © 2021 shanyemangfu.com. ALL RIGHTS RESERVED.

    Theme Kratos Made By Seaton Jiang

    蜀ICP备15031791号-2