事情是这样的,某天我在项目里临时需要一个图片上传接口来测试功能,简单来说就是从前端上传图片到服务器然后返回一个可访问的静态资源链接,如果为了这个而去开发一个服务端接口实在是麻烦,而对接阿里云、七牛云这类 oss 服务一样要开发而且还要钱,许多免费在线图床也不会提供 API 的功能。。
于是我经过一番摸索,发现其实白嫖 Github 提供的 api 就可以不用服务器 、不花一分钱,简单快速实现我要的上传接口,还自带 https 链接,下面就把详细的过程分享给大家。
0. 注册一个小号
先随便用一个邮箱注册个 Github 小号,注意不要使用你正式的 Github 账户,因为下面创建的 Token 如果做权限管控会比较麻烦,所以我们直接用一个小号来创建仓库,这样可以省去许多工作。
1. 创建 Token
登录你的小号(注意别登错了),访问:github.com/settings/to... ,点击 Generate new token 按钮,创建一个新 Token:
设置一下过期时间,这里我们选择"不会过期 ",然后勾选一下 repo 所有权限:
接着滚到底下点击生成按钮,会看到 Token 生成完毕:
记得复制,Github 不会保存 Token,页面关闭后不可查看。
2. 创建仓库
在小号里创建一个仓库,点击右上角 + 号:
填写仓库名例如:files
,然后点击创建仓库:
创建好后可以看下浏览器的地址栏,把这段 URL 复制一下,这就是你的仓库 repo 名:
至此,我们创建了仓库以及访问令牌,这个小号就没什么作用了,你可以退出该账号。
3. 编写上传方法
做完前面的准备工作,就可以写一个图片上传接口了。
代码十分简单,这里用常见的 axios 作为网络请求库:
js
import axios from 'axios'
const repo = 'shawnphang/files' // 填你的仓库 repo
const cutToken = 'ghp_Znytm1Twnxobl' // 填你的 Token
const tailToken = '0Cp7BjWgKlLpa14opaEzL'
const uploader = async (content) => {
const d = new Date()
const path = `${d.getFullYear()}/${d.getMonth()}/${d.getTime()}${file.name?.split('.').pop() || '.png'}`
const imageUrl = 'https://api.github.com/repos/' + repo + '/contents/' + path
const body = { branch: 'main', message: 'upload', content, path }
const headers = {
Authorization: `token ${cutToken}${tailToken}`,
'Content-Type': 'application/json; charset=utf-8',
}
const res = await axios.put(imageUrl, body, { headers })
// 直接取得返回的图片地址
return res?.content?.download_url
// return `https://fastly.jsdelivr.net/gh/${repo}@main/${path}`
}
如果要使用 jsDelivr 免费加速访问,可以把 return
值改为上面的 https://fastly.jsdelivr.net/gh/${repo}@main/${path}
,但是似乎国内访问速度也是一般般。
注意这里的 Token 被我拆成了
cutToken
和tailToken
两个字段再拼起来,是因为我的代码还要托管到 github 上,如果在代码里直接写出完整 Token 的话会被 github 识别到,然后就自动把你的 Token 从账户里删除了,如果你的代码不会 push 到 github 上,那么可以不用这么做。
4. 上传文件
有了以上方法我们就可以直接调用上传然后获得文件的路径,例如这样:
js
const imgUrl = await uploader(图片内容)
不过目前只支持上传 base64 格式内容,如果通过文件选择获取的 file 格式文件就不能直接上传了,可以用如下方法转换:
js
const reader = new FileReader()
function getBase64(file) {
return new Promise((resolve) => {
reader.onload = function (event) {
const fileContent = event.target.result
resolve(fileContent.split(',')[1])
}
reader.readAsDataURL(file)
})
}
例如我们有一个上传按钮:
html
<input type="file" onChange="selectFile" />
选择图片后上传则在事件回调中处理:
js
const selectFile = async (file) => {
const content = await getBase64(file)
const imgUrl = await uploader(content)
};
得到 imgUrl
即为返回图片访问地址例如 https://xxxx/xxx/xxx.png
结束
其实原理就是调用 github 的 api 来往仓库里提交文件,然后通过对应的 download_url 或 jsDelivr 节点就可以直接访问到了,访问和上传速度什么的肯定不是很理想,但是像我一样用来当小文件上传还是很不错的,完全省去开发成本,简单配置就能一劳永逸。
另外由于众所周知的原因,这个资源访问是不稳定的,只建议在开发环境中应急用,不能在生产项目中使用。
以上就是文章的全部内容了,感谢看到这里!如果觉得写得还不错,对你有所帮助或启发,别忘了点赞收藏关注"一键三连"哦~ 我是茶无味,一名平凡的前端 Developer,希望与你共同成长~