Skip to content

使用又拍云极速搭建图床

前言

某天在群里摸 🐟 ,聊到了图床相关的话题,群友推荐了 又拍云

说有活动,可以白嫖存储,10G + 15G(HTTP/HTTPS 流量) 。笔者之前一直用的七牛云 10G + 10G(回源流量)

又拍云七牛云
注册送1个月的代金券 + 网站挂推广送1年代金券注册即可送每月都有

笔者就花了点时间研究了一下又拍云的 SDK 和对象存储,能力上完全可以平替七牛云,于是就花了一点时间给图床应用加上了又拍云的支持。

效果

大家可以访问 https://imgbed.sugarat.top/ 直接体验,默认已配置 又拍云 存储

下面将介绍 又拍云对象存储配置,关键API用法,如何接入上述图床。

对象存储服务创建

这里直接省略账号注册,参加推广活动等步骤,直接进入对象存储配置页面。

访问对象存储控制台,点击创建服务

这个"服务"和其它平台的 Bucket(桶) 类似,可以理解为存储空间的概念。

填一下服务名称(全平台唯一),绑定账号即可

服务创建完,需要的东西基本都有了,是不是非常简单!

  • 服务名:自定义
  • 账号:自定义
  • 密码:自动生成
  • 域名:测试域名 serviceName.test.upcdn.net

API 使用

token 生成

这里推荐使用 token 认证 根据文档:认证鉴权可知生成方式如下:

看不懂?没关系 GPT 可以帮你,直接复制丢给它。

这不代码就来了。

我们可以适当优化一下,不需要用到第三方库base64-js,直接使用 Node.js 的内置模块crypto 即可。

js
import crypto from 'crypto'

/**
 * 生成 upyun 上传token
 * @param {*} operator 账号
 * @param {*} password 密码
 * @param {*} method 方法(PUT)
 * @param {*} uriPrefix 请求公共前缀
 * @param {*} date 过期时间
 * @returns 上传凭证
 */
function generateUpyunToken(operator, password, method, uriPrefix, date) {
  // 密码的md5值,秘钥
  const secret = crypto.createHash('md5').update(password).digest('hex')

  // 构造用于计算校验值的字符串
  const value = `${method}&${uriPrefix}&${date}`

  // 使用 hmac-sha1 算法生成token
  const token = crypto.createHmac('sha1', secret) // 使用密码的MD5值作为秘钥
    .update(value) // 设置用于计算校验值的字符串
    .digest() // 计算校验值
    .toString('base64') // 转换为base64 格式

  // 组合成要求的格式
  return `UPYUN ${operator}:${token}`
}

代码非常简洁明了,使用方式如下

js
const token = generateUpyunToken('账号',
  '密码',
  'PUT',
  '服务名/资源公共前缀路径', // 服务名 + 公共资源前缀路径构成
  new Date().getTime() + 1000 * 60 * 60 * 24 * 90 // 计算过期时间 90天后的日期
)

理论上这个 token 也可以在前端生成,调用和后端一致的算法即可。

前端上传

① 安装 upyun sdk

sh
npm i upyun

② 上传示例

根据文档,可以看到客户端上传需要的参数。

  • Authorization:前面通过生成的token
  • X-Date:请求日期时间,GMT 格式字符串
  • X-Upyun-Uri-Prefix:服务名 + 资源公共前缀路径
  • X-Upyun-Expire:过期时间

下面就是核心的上传方法。

ts
import upyun from 'upyun'

const service = new upyun.Service('服务名')
const client = new upyun.Client(service, () => ({
  'Authorization': '前面通过生成的token',
  'X-Date': new Date().toUTCString(),
  'X-Upyun-Uri-Prefix': '服务名/资源公共前缀路径',
  'X-Upyun-Expire': date, // 前面生成 Token 时的 date 参数
}))

const sourceKey = '资源公共前缀路径/资源名' // 'test/imgs/abc.png'

// 调用上传
client.putFile(sourceKey, file) // 返回值 Promise<boolean>

③ 方法封装

我们可以简单封装一下,方便调用

ts
interface UPYunConfig {
  /**
   * 服务名
   */
  serviceName: string
  /**
   * 上传凭证
   */
  token: string
  /**
   * 资源公共前缀
   */
  prefix: string
  /**
   * 过期时间 new Date().getTime() + 1000 * 60 * 60 * 24 * 90
   */
  date: number
  /**
   * 域名(用于拼接最后的访问链接)
   */
  domain: string
  /**
   * 最后的资源名,建议使用 uuid 或者文件的 MD5
   */
  filename?: string
}
async function uploadFile(file: File, ops: UPYunConfig) {
  const { serviceName, prefix, token, date, domain, filename } = ops

  const service = new upyun.Service(serviceName)
  const client = new upyun.Client(service, () => ({
    'Authorization': token,
    'X-Date': new Date().toUTCString(),
    'X-Upyun-Uri-Prefix': `${serviceName}/${prefix}`,
    'X-Upyun-Expire': date,
  }))

  const key = `${prefix}/${filename || file.name}`

  const isSuccess = await client.putFile(key, file)
  // 返回最后可以用于访问的链接
  return isSuccess ? Promise.resolve(`${domain}/${key}`) : Promise.reject(new Error('上传失败'))
}

接入纯静态图床

上述逻辑我都封装在了自己的图床应用中:GitHub: image-bed-qiniu

只需要在 cli 目录下,修改 .env 配置文件

sh
# 又拍云相关配置
UPYUN_OPERATOR=operator
UPYUN_PASSWORD=password
UPYUN_BUCKET=service-name
UPYUN_DOMAIN=http://service-name.test.upcdn.net
UPYUN_PREFIX=image
UPYUN_SCOPE=default
# token有效期,默认3个月,单位秒,你可以自行设置(60*60*24*30)
# UPYUN_EXPIRES=2592000

执行 node upyun-token.js 即可生成需要的 token。

将其粘贴配置到 线上的图床应用,或者自己部署的均可 image-bed-qiniu:client

其它

线上使用,推荐 绑定自定义域名 和 开启HTTPS 支持。

这两个直接在平台里根据指引操作即可,步骤也很简单。

最后

后续准备提供一个图床的 Docker 镜像,这样部署起来也更加方便。

大家有其它可白嫖的图床也可推荐推荐一下。