一直想以自己的方式(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}
owner
github用户名repo
仓库名path
表示图片的路径。 例如:你打算把上传newFile.jpg
到根目录下images
文件夹里:/repos/myAccountName/myRepo/contents/images/newFile.jpg
上传界面长这样:
选取图库图片或者拍照后,视图片大小对图片压缩。
压缩的原理:
- 将图片
file
转换为base64
数据 - 创建一个消费该
base64
的img
标签 - 将该
img
标签转化为canvas
元素 - 通过
canvas
的toBlob
方法压缩数据,生成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"
}
})
返回如下:
可以看到返回的数据有图片文件的绝对路径(国内无法正常访问),因此需要根据每个文件的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对象长这样:
转换为base64即可正常显示:
最后
功能开发完毕后,缺个logo,又到wix制作了一个,作为站点的favicon图。
目前整体已完成,仓库地址:GitHub,喜欢的可以给个star。
网站预览:GitHub Page。
最后,听着Enigma的《return to innocence》,悠扬的曲子,彷佛看到未来的我:牵着女儿的小手,旁边是无尽的田野,空气弥漫着稻香,一大一小,一高一低,好像这就是整个世界.