巧用GitHub REST API搭建云相册

1,456 阅读4分钟

一直想以自己的方式(my own way)给出生不久的小女儿一个小礼物:它应该是一个体现了老爸特色(程序员)、恒久的东西。考虑到小孩儿变化快,需要一个东西记录,于是决定做个相册,考虑到可以方便跟踪每次上传记录、有朝一日下载备份,决定将图片存到github仓库

我们已习惯于通过命令行或集成工具与GitHub仓库进行交互,不过GitHub也提供了REST API,让开发者可以通过接口commit、获取仓库的内容,这为了我们实现云相册提供了基础.

功能点分析

首先,有以下几个功能点和问题需要注意:

  • 上传图片。通过API接口上传图片到远程仓库
  • 获取图片列表。通过接口批量获取图片信息
  • 展示图片。由于一些原因GitHub的文件链接无法正常访问,需要多走一步通过接口获取图片的blob数据转换为base64展示
  • GitHub提供的接口只支持获取不超过1MB的图片文件,因此我们在上传图片时要对图片压缩处理。

实施步骤

创建仓库、配置access token

首先创建一个新的仓库,然后配置access token: 在这里插入图片描述 然后点击确认生成,保存该token到一个安全的地方,它不会再出现: 在这里插入图片描述 然后在接下来的接口请求头中携带该Token:Authorization:token ghp_C2312321sdsaeqweqevd

注意:不要将该token以明文的形式放到仓库里,因为一方面非常不安全,另一方面GitHub会识别出来从而自动将token删除作废

上传图片

上传文件的URL格式为:put /repos/{owner}/{repo}/contents/{path}

  • ownergithub用户名
  • repo仓库名
  • path表示图片的路径。 例如:你打算把上传newFile.jpg到根目录下images文件夹里:/repos/myAccountName/myRepo/contents/images/newFile.jpg

上传界面长这样:

image.png

选取图库图片或者拍照后,视图片大小对图片压缩。

压缩的原理:

  • 将图片file转换为base64数据
  • 创建一个消费该base64img标签
  • 将该img标签转化为canvas元素
  • 通过canvastoBlob方法压缩数据,生成size合适的blob
  • blob转化成file

具体可以参考MDN上toBlob方法

然后将压缩后的file再转换为base64,因为Github上传接口仅支持base64数据,然后调用上传接口:

//将毫秒数和描述作为文件名,从base64里获取文件后缀名
var fileName = Date.now() + "_" + desc +"." + bs64.match(/data:image\/(\w+)/)[1];
//本次上传的message,类似于每次commit添加的信息
var message = "测试信息"
fetch("https://api.github.com/repos/anderlaw/gallery/contents/images/" + fileName, {
    method: "put",
    headers: {
      Authorization:"token ghp_C2312321sdsaeqweqevd",
      Accept:"application/vnd.github.v3+json"
    },
    body: JSON.stringify({
      message: message,
      //Github只允许严格的base64内容,需要截掉文件类型和base64标识。
      content: base64.split("base64,")[1],
    }),
}

注意:GitHub只允许严格的base64数据,须截掉开头部分,例如 data:image/jpeg;base64,/9j/4AAQSkZJRgABAQEAYABgAAD/,应该为:/9j/4AAQSkZJRgABAQEAYABgAAD/,否则GitHub无法正常解析。

显示图片

先获取images目录下的所有图片文件信息。

获取某目录下文件列表接口格式为:get /repos/{owner}/{repo}/contents/{path}

fetch("https://api.github.com/repos/anderlaw/gallery/contents/images",{
    method: "get",
    headers: {
      Authorization:"token ghp_C2312321sdsaeqweqevd",
      Accept:"application/vnd.github.v3+json"
    }
})

返回如下:

image.png

可以看到返回的数据有图片文件的绝对路径(国内无法正常访问),因此需要根据每个文件的path属性调取接口获取图片的数据。

var filePath = "images/laughter.jpg"
fetch("https://api.github.com/repos/anderlaw/gallery/contents/"+filePath, {
    headers: {
      Authorization:"token ghp_C2312321sdsaeqweqevd",
      Accept:"application/vnd.github.v3+json"
    },
}).then(function (res) {
  return res.blob();
})
.then(function (blob) {
  console.log(blob)
})

打印的blob对象长这样:

image.png

转换为base64即可正常显示:

image.png

最后

功能开发完毕后,缺个logo,又到wix制作了一个,作为站点的favicon图。

目前整体已完成,仓库地址:GitHub,喜欢的可以给个star。

网站预览:GitHub Page

最后,听着Enigma的《return to innocence》,悠扬的曲子,彷佛看到未来的我:牵着女儿的小手,旁边是无尽的田野,空气弥漫着稻香,一大一小,一高一低,好像这就是整个世界.