Node.js操作七牛云OSS进行多文件压缩为zip的方法

本文涉及的产品
对象存储 OSS,OSS 加速器 50 GB 1个月
简介: Node.js操作七牛云OSS进行多文件压缩为zip的方法

前言


最近在用七牛云对象存储服务做了一个小应用


需要用到批量下载文件的操作,qiniu-OSS-SDK只直接提供了单个文件的下载方法,批量下载得自己组装


这里批量下载的实现逻辑如下:

  1. 对要下载的资源归档到一个ZIP压缩包里
  2. 下载这个压缩包


不得不吐槽,这部分的文档对新手很不友好,直接看蒙

下面展开介绍


准备工作


项目中安装qiniu依赖


npm i qiniu


鉴权代码,通过accessKeysecretKey鉴权


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 如图


网络异常,图片无法展示
|


归档完成后即可调用下载资源文件的方法,下载归档的文件


参考


相关实践学习
对象存储OSS快速上手——如何使用ossbrowser
本实验是对象存储OSS入门级实验。通过本实验,用户可学会如何用对象OSS的插件,进行简单的数据存、查、删等操作。
相关文章
|
资源调度 JavaScript
nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
nodeJS 的 npm 设置国内高速镜像之淘宝镜像的方法
9278 2
|
JavaScript Windows
Win7内网安装高版本的Node方法,亲测有效node-v16.16.0
Win7内网安装高版本的Node方法,亲测有效node-v16.16.0
3401 1
|
10月前
|
监控 负载均衡 JavaScript
有哪些有效的方法可以优化Node.js应用的性能?
有哪些有效的方法可以优化Node.js应用的性能?
492 69
|
9月前
|
JavaScript Linux 内存技术
Debian 11系统下Node.js版本更新方法详解
本指南详细介绍在Linux系统中安装和管理Node.js的步骤。首先检查现有环境,包括查看当前版本和清除旧版本;接着通过NodeSource仓库安装最新版Node.js并验证安装结果。推荐使用nvm(Node Version Manager)进行多版本管理,便于切换和设置默认版本。同时,提供常见问题解决方法,如权限错误处理和全局模块迁移方案,以及版本回滚操作,确保用户能够灵活应对不同需求。
947 0
|
9月前
|
JavaScript Linux 内存技术
Debian 11系统下Node.js版本更新方法
Debian 11更新Node.js主要就是这三种方式,无论你是初涉其中的新手还是找寻挑战的专家,总有一种方式能满足你的需求。现在,你已经是这个
1065 80
|
Kubernetes Ubuntu Windows
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
【Azure K8S | AKS】分享从AKS集群的Node中查看日志的方法(/var/log)
400 3
|
监控 JavaScript Java
Node.js中内存泄漏的检测方法
检测内存泄漏需要综合运用多种方法,并结合实际的应用场景和代码特点进行分析。及时发现和解决内存泄漏问题,可以提高应用的稳定性和性能,避免潜在的风险和故障。同时,不断学习和掌握内存管理的知识,也是有效预防内存泄漏的重要途径。
1020 159
|
存储 JavaScript 搜索推荐
Node框架的安装和配置方法
安装 Node 框架是进行 Node 开发的第一步,通过正确的安装和配置,可以为后续的开发工作提供良好的基础。在安装过程中,需要仔细阅读相关文档和提示,遇到问题及时解决,以确保安装顺利完成。
1084 155
|
JavaScript Linux
2022年超详细在CentOS 7上安装Node.js方法(源码安装)
这篇文章介绍了在CentOS 7系统上通过源码安装Node.js的详细步骤,包括从官网下载Node.js源码包、将安装包上传至虚拟机、解压安装包、删除压缩文件、编译安装Node.js、检查Node.js和npm版本,以及切换npm源到淘宝镜像以加速下载。此外,还提供了一个获取Linux下Node.js离线安装包的微信公众号搜索方式。
|
监控 Java Serverless
函数计算产品使用问题之对于OSS打包的zip的保存目录,该如何操作
阿里云Serverless 应用引擎(SAE)提供了完整的微服务应用生命周期管理能力,包括应用部署、服务治理、开发运维、资源管理等功能,并通过扩展功能支持多环境管理、API Gateway、事件驱动等高级应用场景,帮助企业快速构建、部署、运维和扩展微服务架构,实现Serverless化的应用部署与运维模式。以下是对SAE产品使用合集的概述,包括应用管理、服务治理、开发运维、资源管理等方面。
258 6