七牛云是国内一家领先的云存储公司,可以利用七牛云存储对象存储图片。虽然现在各种图床,但还是希望能够搭建一个私有的图床。所以一直有希望使用七牛云搭建图床的想法,之前一直没有好好地看懂七牛云的 SDK,后来在仔细地看了一遍之后,终于知道如何利用官方的 SDK 来实现图片上传。过年在家花了一点时间,后来陆续也写了一点,完成了这个七牛云图床 chrome 拓展。

注册账户

首先你可以通过这个链接注册你的七牛云账户。在成功注册账户之后,可能还需要绑定手机号,你就可以创建存储空间,可以理解成为文件存储的文件夹。

clipboard.png

创建好存储空间(bucket)就已经完成了私有图库的第一步。

开发

在这也会对所有代码一一解释,主要是讲解一下在开发中遇到的一些问题。首先基于七牛云存储开发,有必要学会七牛云存储 API 的使用。可以在官方 SDK 文档获取所有文档。本拓展的开发主要是基于 js 来进行开发,因此我们只需要了解 js SDK 文档

文档中提到了一点:JS-SDK 依赖服务端颁发 token,可以通过以下二种方式实现:

第一个方法还需要搭建服务器来颁发 token,显然这种方法不太经济,如果仅仅是为了这个图床搭建一个后端服务,就不太划算了。因此,我选择第二种,在客户端来生成 token。这种方法就需要你了解上传策略以及上传凭证。

上传策略是资源上传时附带的一组配置设定。通过这组配置信息,七牛云存储可以了解用户上传的需求:它将上传什么资源,上传到哪个空间,上传结果是回调通知还是使用重定向跳转,是否需要设置反馈信息的内容,以及授权上传的截止时间等等。上传策略主要是 scope 和 dealine 这两个字段是必须要的。scope 是指定上传的目标资源空间 Bucket 和资源键 Key,这里我们只需要设置 bucket。deadline 是上传凭证有效截止时间。Unix时间戳,单位为秒。该截止时间为上传完成后,在七牛空间生成文件的校验时间,而非上传的开始时间,官方建议建议设置为上传开始时间 + 3600s。

function genPolicy(scope) {
  let policy = {
    scope: scope,
    deadline: (new Date()).getTime() + 3600
  }
  return policy;
}

clipboard.png

按照上述算法流程构建客户端的上传 token,官方有提供上传凭证的在线示例,通过整理形成了自己的 token.js

完成本地 token 的,我的开发就完成了一大步。这个拓展需要两个界面的设置,就是包括图片上传页面以及七牛云存储配置页面。关于这两个页面的设计,我也就不一一赘述,主要讲几点:

七牛云信息存储

为了上传图片,我们需要配置 AK,SK,bucket 以及 domain。这些都可以在七牛云的控制台里面获取,因此我们需要在首次打开拓展的时候检查是否具有这些数据。至于这些配置信息保存在什么地方,一开始打算采取的是 chrome.storage 来进行存储,这样做的好处是可以利用账号同步数据,但缺点是操作不方便,是异步的。后来还是决定使用 localStorage,一来使用起来非常方便,二是我们并不是特别需要账号同步。因此,我们首先会检查配置信息是否存储在 localStorage,否则就打开配置页:

  const keys = ['ak', 'sk', 'bucket', 'domain'];
  let isConfig = true;
  
  keys.forEach(key => {
    if (!localStorage[key]) {
      isConfig = false;
    }
  })

  if (!isConfig) {
    chrome.tabs.create({url: 'options.html'});
  }

options

另外一个问题是如果配置页打开时,无法在拓展程序弹出页面添加图片,暂时不知道是什么原因导致的。解决办法是在保存配置之后,设置延时关闭当前 tab。

        setTimeout(() => {
        chrome.tabs.query({currentWindow: true, active: true}, function(tabs) {
          chrome.tabs.remove(tabs[0].id);
        })
      }, 1500)

目前图片有有种上传方式:即选择文件上传或者拖着拖放图片上传,这个主要是通过七牛云的官方 SDK 来实现。SDK 提供了多种事件绑定。另外值得注意的一点       是 FileUploaded 事件返回的 info.res 是一个字符串,需要序列化成 json 格式来使用。

另外值得一提的是利用 css 的 :hover 的属性来实现链接格式 button 的出现,只需要点击 button 就可以将链接复制到剪切板。

  upload

 function copyToClipboard(input) {
 const el = document.createElement('textarea');
 el.style.fontsize = '12pt'
 el.style.border = '0'
 el.style.padding = '0'
 el.style.margin = '0'
 el.style.position = 'absolute'
 el.style.left = '-9999px'
 el.setAttribute('readonly', '')
 el.value = input

 document.body.appendChild(el)
 el.select()

 let success = false;
 try {
   success = document.execCommand('copy', true);
 } catch (err) { }

 document.body.removeChild(el);

 return success;
}

拓展安装

这个拓展最终也在 chrome 商店上架了。拓展的安装方式有两种,第一种就是去chrome 商店去安装,这种方式是推荐的,不过需要科学上网。另外一种就是去项目仓库下载项目文件,然后在 chrome://extensions 选择以开发者模式加载已解压的拓展程序。

结语

现在各种图床层出不穷,我这也是重复造轮子。但是在理解 SDK 以及探索其使用,并且最终形成这个拓展程序的过程还是非常有意思的。陆陆续续花了一个多礼拜的时间完成这个拓展程序的开发,目前拓展程序仍然为 beta 版本,欢迎大家使用,有任何建议可以在 https://github.com/neal1991/image-host 提 issue,欢迎 star 以及 pr。

以上

欢迎搜索微信号 mad_coder 或者扫描二维码关注公众号:

9tMvlT.jpg