前言
最近在用七牛云对象存储服务做了一个小应用
需要用到批量下载文件的操作,qiniu-OSS-SDK
只直接提供了单个文件的下载方法,批量下载得自己组装
这里批量下载的实现逻辑如下:
- 对要下载的资源归档到一个ZIP压缩包里
- 下载这个压缩包
不得不吐槽,这部分的文档对新手很不友好,直接看蒙
下面展开介绍
准备工作
项目中安装qiniu
依赖
npm i qiniu
鉴权代码,通过accessKey
与secretKey
鉴权
const qiniu = require('qiniu') const qiniuConfig = { accessKey: process.env.qiniu_accessKey, secretKey: process.env.qiniu_secretKey } const mac = new qiniu.auth.digest.Mac(qiniuConfig.accessKey, qiniuConfig.secretKey)
公共参数
// 空间名称 const bucket = 'bucket' // 空间绑定的域名 const privateBucketDomain = 'http://example.com'
依赖方法汇总
上传凭证获取
凭证默认1小时有效,客户端需要此凭证进行上传鉴权
function getUploadToken(): string { const putPolicy = new qiniu.rs.PutPolicy({ scope: bucket, // expires: 3600, // returnBody: '{"key":"$(key)","hash":"$(etag)","fsize":$(fsize),"bucket":"$(bucket)","name":"$(x:name)"}' }) return putPolicy.uploadToken(mac) }
通过returnBody可以自定义上传成功的响应参数
获取OSS文件的下载链接
const getDeadline = () => { // 12小时过期 return Math.floor(Date.now() / 1000) + 3600 * 12 } /** * 获取OSS上文件的下载链接 * @param key 文件的key * @param expiredTime 链接过期的具体时间 */ function createDownloadUrl(key, expiredTime = getDeadline()) { const config = new qiniu.conf.Config() const bucketManager = new qiniu.rs.BucketManager(mac, config) return bucketManager.privateDownloadUrl(privateBucketDomain, key, expiredTime) }
多个资源归档为压缩包
这个地方文档非常模糊,需要耗费不少时间试错,需要用到前面提到的:
- 获取资源下载链接方法
- 获取资源上传凭证方法
资源归档方法
const path = require('path') const qiniu = require('qiniu') const { urlsafeBase64Encode } = qiniu.util function getKeyInfo(key: string) { const { name, base, ext } = path.parse(key) return { name, base, ext, } } /** * 资源归档为zip * @param {string[]} keys 需要归档的资源 * @param {string} zipName 压缩包名称 * @returns */ function makeZipWithKeys(keys, zipName){ return new Promise((res) => { const names = [] const content = keys.map((key) => { // 拼接原始url // 链接加密并进行Base64编码,别名去除前缀目录。 const keyInfo = getKeyInfo(key) const { name, ext } = keyInfo let { base } = keyInfo // 判断别名是否存在,存在则后缀+数字自增 let i = 1 while (names.includes(base)) { base = `${name}_${i}${ext}` i += 1 } names.push(base) const safeUrl = `/url/${urlsafeBase64Encode(createDownloadUrl(key))}/alias/${urlsafeBase64Encode(base)}` return safeUrl }).join('\n') const config = new qiniu.conf.Config({ zone: qiniu.zone.Zone_z2 }) const formUploader = new qiniu.form_up.FormUploader(config) const putExtra = new qiniu.form_up.PutExtra() const key = `${Date.now()}-${~~(Math.random() * 1000)}.txt` formUploader.put(getUploadToken(), key, content, putExtra, (respErr, respBody, respInfo) => { if (respErr) { throw respErr } if (respInfo.statusCode == 200) { const { key } = respBody // 执行压缩 ,设置压缩资源的在OSS上的保存路径 const zipKey = urlsafeBase64Encode(`${bucket}:temp_package/${Date.now()}/${zipName}.zip`) const fops = `mkzip/4/encoding/${urlsafeBase64Encode('gbk')}|saveas/${zipKey}` const operManager = new qiniu.fop.OperationManager(mac, config) const pipeline = '' // 使用公共队列 // 下行。不知用处 const options = { force: false } operManager.pfop(bucket, key, [fops], pipeline, options, (err, respBody, respInfo) => { if (err) { throw err } if (respInfo.statusCode == 200) { // 可直接通过statusUrl查询处理状态 const statusUrl = `http://api.qiniu.com/status/get/prefop?id=${respBody.persistentId}` console.log(statusUrl) // 这里只返回任务id,转由客户端发请求查询 res(respBody.persistentId) } else { console.log(respInfo.statusCode) console.log(respBody) } }) } else { console.log(respInfo.statusCode) console.log(respBody) } }) }) }
查看资源归档完成状态
/** * 查询Fop任务完成状态 * @param {string} persistentId * @returns */ function checkFopTaskStatus(persistentId){ const config = new qiniu.conf.Config() const operManager = new qiniu.fop.OperationManager(null, config) return new Promise((res) => { operManager.prefop(persistentId, (err, respBody, respInfo) => { if (err) { console.log(err) throw err } if (respInfo.statusCode == 200) { // 结构 ![图片](https://p3-juejin.byteimg.com/tos-cn-i-k3u1fbpfcp/011f49a2692343aba42dc182895b86d7~tplv-k3u1fbpfcp-zoom-1.image) const item = respBody.items[0] const { code, key } = item res({ code, key }) } else { console.log(respInfo.statusCode) console.log(respBody) } }) }) }
响应的 respBody
如图
网络异常,图片无法展示
|
归档完成后即可调用下载资源文件的方法,下载归档的文件