最近在毕设中使用了七牛云的对象存储,发现挺多坑的(主要是官方文档太全太多,太过花里胡哨),故此简要写一下个人简单使用七牛云的过程以及一些注意事项。
创建空间
注册账号(并且身份验证)后,直接点击对象存储创建一个空间,其中存储空间名称即是文档中的Bucket。存储区域选择就近原则,访问控制为公开(私有获取图片都需要密钥,很麻烦)。
CDN加速域名
创建空间后,会分配一个临时测试域名,有效期为30天,此时没有域名的朋友就需要注册并备案一个域名,又或者借一个域名,如小明有xiaoming.top的域名,你可以叫他创建一个三级域名解析:qiniu(或其他).xiaoming.top的CNAME记录类型的解析,记录值为七牛云创建域名后产生的值(即先在七牛云处添加指定的(三级)域名,拿到记录值后添加域名解析即可)。
上传资源
token生成
代码上传需要获取token,token建议后台生成,再由前端获取。官方提供了各种语言的SDK,此处以node.js为例Node.js SDK_SDK_对象存储 - 七牛开发者中心。 根据文档创建一个qiniuUtil.ts的文件用于生成token(js自行修改部分语法),AccessKey与SecretKey在七牛云的个人中心=>密钥管理处查看,bucket为存储空间名:
import * as qiniu from "qiniu";
import { qiniuConfig } from "../config";
const upTokenCreate = (
ak: string,
sk: string,
bucket: string,
time?: number,
key?: string
) => {
const mac = new qiniu.auth.digest.Mac(ak, sk);
const options = {
scope: bucket + (key ? `:${key}` : ""),
expires: time || 2 * 60 * 60
};
const putPolicy = new qiniu.rs.PutPolicy(options);
const uploadToken = putPolicy.uploadToken(mac);
return uploadToken;
};
const { accessKey, secretKey, bucket } = qiniuConfig;
// 普通上传
export const upToken = () =>
upTokenCreate(accessKey, secretKey, bucket, 24 * 60 * 60);
/**
* 覆盖上传
* @param key 强制覆盖上传的key(路径名)
*/
export const forceUpToken = (key: string) =>
upTokenCreate(accessKey, secretKey, bucket, 5 * 60, key);
前端上传
上传路径根据空间存储区域设置,存储区域_产品手册_对象存储 - 七牛开发者中心。
客户端上传可以根据官方提供的JavaScript SDK_SDK_对象存储 - 七牛开发者中心,或者使用表单简单上传:表单上传_产品手册_对象存储 - 七牛开发者中心,又或者个人封装。
基于Axios封装可以参考这篇文章。
以下是个人react中基于antd的Upload组件再封装的,主要是action改为https://upload-z2.qiniup.com(华南地区,其他区域自行查询修改),data的key即为存储路径,token为后台拿到的uploadToken,name固定必须为"file",代码如下:
<Upload
ref={ref}
className={className}
listType={listType}
accept={accept || "image/*"}
showUploadList={false}
action="https://upload-z2.qiniup.com"
beforeUpload={handleBeforeUpload}
onChange={onChange}
name="file"
data={{token: forceToken || token, key: path}}
>
{children}
</Upload>
关于资源管理
直接使用SDK就好了,有丰富的例子,直接参考即可。Node.js SDK_SDK_对象存储_资源管理 - 七牛开发者中心
关于覆盖上传的吐槽
- 七牛云同名路径普通上传会直接取消上传,返回上传成功回调!!!
- 虽然!有上传策略可以配置覆盖上传(麻烦,每次上传都要对应路径的专属token)
- 但是!因为cdn的存在,资源不会立即更新,拿到的文件还是覆盖前的文件
- 虽然!!有刷新cdn文件的api。
- 但是!!刷新后是有几秒到十几秒的延迟,对于及时性高的文件图片,很无解!无法立即显示最新的。
- 虽然!!!可以通过url尾部添加参数(?h=xxx),强制cdn回源
- 但是!!!如果是以时间戳为参数,则意味着每次获取数据cdn都会回源,特别浪费流量!
- 虽然!!!!可以database记录文件uid,统一以uid作为参数
- 但是!!!!贼鸡儿麻烦,每次更新都要更新database,完全失去了原本覆盖上传省事的目的啊。
总结:没特殊情况尽量不覆盖上传!怕空间挤爆七牛云有提供delete文件的api,每次更新文件时delete旧的就好了。