Node下载阿里OSS存储文件【不知目录结构】

news/2024/3/29 7:37:02/文章来源:https://blog.csdn.net/jinchunye/article/details/129251956

前言:前端传模型ID,后台根据ID去阿里OSS存储下载对应文件(不知文件内部层级结构,且OSS只能单个文件下载),打包成zip字节流形式返回给前端下载。

需求分析:

  • 生成OSS文件关系树
  • Node做文件下载存储
  • 打包返回给前端

一、前期准备

OK! 现在我们做完了需求调研,当然也要确认技术基本架构,因为这个需求是针对模型资源的,后期会继续累加对应需求(上传、拷贝、预览、引用、编辑等),领导要求分模块构建项目,故新构建一个后台项目,如下:

  • dependencies
    • Koa2(body、router、cors) + mysql2(sequelize) + adm-zip + ali-oss
  • devDependencies
    • dotenv + nodemon

image.png

二、完成业务需求

1.生成OSS文件关系树

我们开发是对接的ali-oss开发文档,会调用内置文件操作api,代码中会写明。
代码遵循单一原则

// 获取目录和文件地址
async function getUrl(url, modelId) {// modelOSS.listV2, 列举文件层级最深值为100return await modelOSS.listV2({prefix: url ? url : "models/" + modelId + '/',// 设置正斜线(/)为文件夹的分隔符。delimiter: "/",});
}
// 获取文件夹数组集合 和 文件数组集合
// 思路:
//     判断是否是最后一层,
//     使用递归把每一层的文件夹或文件地址存储到数组
//     运用闭包做数据持久化async function getPathArr(modelId){const prefixesArr = []; // 文件夹数组集合const objectsArr = []; // 文件数组集合let isFirst = true;const resultPaths = async (url) => {const resultList = await getUrl(url, modelId); // 获取目录if(resultList.prefixes) {// 获取文件夹resultList.prefixes.forEach(async (subDir) => {prefixesArr.push(subDir);// console.log("SubDir: %s", subDir);});}if(resultList.objects) {// 获取文件resultList.objects.forEach(async (obj) => {objectsArr.push(obj.name);// console.log("Object: %s", obj.name);});}if(url)	isFirst = false;}if(isFirst) await resultPaths();for(let i = 0; i < prefixesArr.length; i++){if(prefixesArr[i].substr(-1) === '/'){await resultPaths(prefixesArr[i])}}return {prefixesArr,objectsArr}
}

返回数据如下,每个模型ID返回的对应文件都可能不同

image.png

2.Node做文件下载存储

  • fs中间件不支持逐级创建文件路径,故手写一个公共方法:

    // 通过文件地址,逐级创建文件夹
    function newFolders(folderPath) {const arr = folderPath.split('/') // 分割字符串let path = ''arr.forEach((value, i) => {path += value + '/'if (!fs.existsSync(path)) {  //判断是否存在该目录fs.mkdirSync(path)}})
    }
    
  • type判断传过来的路径类型(文件或文件夹),分类创建或下载

    // 通过远端模型文件层级生成文件夹,下载文件
    async function downloadModelFile(targeDirList, type){try{if(type){const result = await modelOSS.getStream(targeDirList); // 下载文件// 创建文件并且写入const writeStream = fs.createWriteStream(`src/examplefile/${targeDirList}`);result.stream.pipe(writeStream);} else {// 查看是否有此目录,如果没有则创建if (!fs.existsSync(`src/examplefile/${targeDirList}`)){newFolders(`src/examplefile/${targeDirList}`);}}}catch(e){console.log(e)}
    }
    
  • 本地与远端文件一致时,打包文件

    async function downFile(targeDirList, type, modelId) {// targeDirList => 文件或文件夹远端地址// type => 如果传入代表是文件// modelId => 模型ID// 如果是文件夹的话直接创建,是文件的话直接下载try {for (let i = 0; i < targeDirList.length; i++) {downloadModelFile(targeDirList[i], type); // 文件下载let loopNum = i + 1;   if (loopNum === targeDirList.length) {var zip = new AdmZip();// 压缩文件夹zip.addLocalFolder('src/examplefile/models/' + modelId);zip.writeZip('src/examplefile/models/' + modelId + '.zip');}}} catch (e) {console.log(e);return e.status;}
    }
    

生成如下:
image.png

3.返回给前端

// 抛出模型下载接口
async function exportModel(ctx, next) {try {const { modelId } = ctx.request.body;// 获取文件夹数组集合 和 文件数组集合const { prefixesArr, objectsArr } = await getPathArr(modelId);// 目录生成await downFile(prefixesArr);// 文件下载到对应目录中await downFile(objectsArr, 'prefixes', modelId);// 前端请求返回let userfilepath = `src/examplefile/models/${modelId}.zip`;let resultData;let stat = fs.readFileSync(`src/examplefile/models/${modelId}.zip`);if(fs.existsSync(userfilepath)) {resultData = stat.toString('base64');} else {resultData = { code: 500,message: "模型文件不存在"};}ctx.body = resultData;} catch (e) {console.log(e);}
}

image.png

总结

时间过得总是好快,一转眼就过了午休的时间,一转眼也快走过了三年,这篇文章只是对需求的分析和初步的代码实现,大家看着图一乐就好,今天上午我们新的领导给我们开会了,这里与大家共勉:
1.找重点的事来做。
2.让自己有时间思考。
3.自身为核心。

最后

水平有限,还不能写到尽善尽美,希望大家多多交流,跟春野一同进步!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.luyixian.cn/news_show_74962.aspx

如若内容造成侵权/违法违规/事实不符,请联系dt猫网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kafka(一) 的架构,各概念

Kafka架构 Kafak 总体架构图中包含多个概念&#xff1a; &#xff08;1&#xff09;ZooKeeper&#xff1a;Zookeeper负责保存broker集群元数据&#xff0c;并对控制器进行选举等操作。 &#xff08;2&#xff09;Producer&#xff1a; 生产者负责创建消息&#xff0c;将消息发…

【神经网络】LSTM为什么能缓解梯度消失

1.LSTM的结构 我们先来看一下LSTM的计算公式&#xff1a; 1.遗忘门&#xff1a; 2.输入门&#xff1a; 3.细胞状态 4.输出门 2.LSTM的梯度路径 根据LSTM的计算公式&#xff0c;可以得出LSTM的cell state与、、都存在计算关系&#xff0c;而、、的计算公式又全部都与有关&#x…

RPC异步化原理

深入RPC&#xff0c;更好使用RPC&#xff0c;须从RPC框架整体性能考虑问题。得知道如何提升RPC框架的性能、稳定性、安全性、吞吐量及如何在分布式下快速定位问题。RPC框架如何压榨单机吞吐量&#xff1f; 1 前言 TPS一直上不去&#xff0c;压测时CPU压到40%&#xff5e;50%就…

bug的创建和等级

1.如何合理的创建一个bug 创建bug的要素 &#xff1a;问题的版本&#xff0c;发现问题的环境&#xff0c;发现问题的步骤&#xff0c;预取结果&#xff0c;实际结果。 eg&#xff1a; 1.问题的版本&#xff1a;谷歌浏览器108版本 2.发现问题的环境&#xff1a;windows11家庭版…

CHAPTER 2 CentOS的日志系统(日志工具)

日志工具2.1 rsyslogd(syslogd)2.1.1 介绍2.1.2 语法2.1.3 配置文件syslog.conf2.1.4 syslog.conf的配置规则2.1.5 示例2.2 logrotate2.2.1 介绍2.2.2 配置文件2.2.3 示例一2.2.4 示例二2.3 dmesg2.3.1 命令简介2.3.2 使用示例2.4 关于重启/死机的日志2.4.1 last2.4.2 日志查看…

HTML#5表单标签

一. 表单标签介绍表单: 在网页中主要负责数据采集功能,使用<form>标签定义表单表单项: 不同类型的input元素, 下拉列表, 文本域<form> 定义表单<input> 定义表单项,通过typr属性控制输入形式<label> 为表单项定义标注<select> 定义下拉列表<o…

工程机械焊接件焊接结构件三维扫描检测外观质量控制-CASAIM三维扫描检测仪

焊接已发展为制造业中的一种重要的加工方法&#xff0c;广泛应用于航空、航天、冶金、石油、汽车制造以及国防等领域。工程机械焊接件品种繁多、几何形状复杂&#xff0c;焊接件质量的好坏将直接影响到产品的使用寿命长短。对焊缝表面尺寸测量及评定表面焊缝缺陷时&#xff0c;…

叠氮试剂79598-53-1,6-Azidohexanoic Acid,6-叠氮基己酸,末端羧酸可与伯胺基反应

●中文名&#xff1a;6-叠氮基己酸●英文名&#xff1a;6-Azidohexanoic Acid&#xff0c;6-Azidohexanoic COOH●外观以及性质&#xff1a;西安凯新生物科技有限公司供应的6-Azidohexanoic Acid浅黄色或者无色油状&#xff0c;叠氮化物可使用铜催化的Click化学与末端炔烃共轭&…

一文了解 requestAnimationFrame

requestAnimationFrame 的基本使用 requestAnimationFrame 是什么 window.requestAnimationFrame() 告诉浏览器——你希望执行一个动画&#xff0c;并且要求浏览器在下次重绘之前调用指定的回调函数更新动画。该方法需要传入一个回调函数作为参数&#xff0c;该回调函数会在浏…

腾讯前端二面常考vue面试题(附答案)

虚拟DOM真的比真实DOM性能好吗 首次渲染大量DOM时&#xff0c;由于多了一层虚拟DOM的计算&#xff0c;会比innerHTML插入慢。正如它能保证性能下限&#xff0c;在真实DOM操作的时候进行针对性的优化时&#xff0c;还是更快的。 MVVM的优缺点? 优点: 分离视图&#xff08;V…

MK60DX256VLQ10(256KB)MK60DN256VLQ10 Kinetis K60 MCU FLASH

MK60DX256VLQ10(256KB)MK60DN256VLQ10 Kinetis K60 MCU 32BIT 256KB FLASH 144LQFP【说明】Kinetis K6x MCU系列是一个可扩展的组合&#xff0c;具有不同级别的集成&#xff0c;提供丰富的模拟、通信、定时和控制外设套件&#xff0c;以适应广泛的需求。应用楼宇自动化控制器人…

数仓基础与hive入门

目录1、数仓数据仓库主流开发语言--SQL2、Apache Hive入门2.1 hive定义2.2 为什么使用Hive2.3 Hive和Hadoop关系2.4 场景设计&#xff1a;如何模拟实现Hive功能2.5 Apache Hive架构、组件3、Apache Hive安装部署3.1 metastore配置方式4、Hive SQL语言&#xff1a;DDL建库、建表…

【谷歌grc】recaptcha browser-error 错误

grc 谷歌人机验证错误 https://www.google.com/recaptcha/api/siteverif 返回错误信息 browser-error [{"success": false,"error-codes": ["browser-error"] }]之前都是调通能用的&#xff0c;突然之间就不能用了&#xff0c;查了半天也没有找…

蓝库云|什么是供应链管理?SCM对制造业的重要性

企业在产品的销售经营上&#xff0c;往往不会考量到供应链管理(SCM)的流程规划&#xff0c;但现今的商业环境与以往不同&#xff0c;高度竞争与客户不断提升的期望&#xff0c;藉由做好供应链管理(SCM)&#xff0c;才能更准时的提供优质产品与优良服务&#xff0c;增强企业竞争…

Qt 小项目 图片浏览系统

目录 引言 实现功能&#xff1a; 效果&#xff1a; 实现图片浏览所用知识: 实现流程&#xff1a; 实现环境和UI设计 具体实现 引言 本系统支持&#xff0c;自动播放&#xff0c;左右拖动切换&#xff0c;点击列表切换&#xff0c;点击按钮切换&#xff1b;是一个标准的…

职场性别报告,男女薪酬仍有差距,男性平均薪酬比女性高29.7%

性别是否影响职业&#xff1f;女性求职比男性更加困难&#xff1f;男性薪酬比女性更有优势&#xff1f;人们一说到警察、建筑师通常会想到高大魁梧的男性形象&#xff0c;一说到幼师、护士往往想到的都是温柔的女性形象&#xff0c;职业好似与性别挂钩&#xff1b;女性求职通常…

vue脚手架多页自动化生成实践

前言 在前端开发过程中&#xff0c;常常面对多种业务场景。到目前为止&#xff0c;前端对于不同场景的处理通常会采用不同的渲染方案来组合处理&#xff0c;常见的渲染方案包括&#xff1a;CSR(Client Side Rendering)、SSR(Server Side Rendering)、SSG(Static Site Generati…

LVGL8.3 集成 ST7789V 显示驱动和 CST816T 触摸屏驱动

LVGL8.3 集成 ST7789V 显示驱动和 CTS816S 触摸屏驱动起因效果&#xff08;正常显示&#xff0c;触摸屏可调换X&#xff0c;Y轴&#xff09;使用方式前提操作步骤最后参考起因 LVGL的ESP32 Drivers库中已经包含了大多数显示和触摸芯片的驱动&#xff0c;基本上只需要在MenuCon…

一些无线通信系统模型的概念

一些无线通信系统模型的概念 扩频通信,指的是系统的带宽WWW远大于其信息传输速率R(bits/s)R(bits/s)R(bits/s), 定义展频带因子BeWRB_e \frac{W}{R}Be​RW​, 易知在扩频通信系统中,BeB_eBe​远大于1. 在频率上产生如此大的冗余度,主要是为了减轻无线通信或卫星通信中经常产生…

SpringMVC——响应处理(1)【包含源码分析】

Controller public class JsonReturnController {ResponseBodyGetMapping("/getPet")public Pet getPet(){Pet petnew Pet();pet.setAge(5);pet.setName("lily");return pet;} }项目启动后 浏览器输入 http://localhost:8080/getPet 。 debug DispatcherS…