首页 > 其他分享 >记一次 OSS 大批量文件下载的实现 → bat脚本不好玩!

记一次 OSS 大批量文件下载的实现 → bat脚本不好玩!

时间:2023-11-06 09:23:48浏览次数:57  
标签:文件 bat 不好玩 %% OSS yzb qsl ossutil 下载

开心一刻

  一天夜里,侄女跟我哥聊天

  侄女一脸期待的看着我哥:爸爸,你说妈妈和奶奶谁漂亮啊?

  我哥不慌不忙的拿起一粒瓜子,轻声说道:为啥没有你啊?

  侄女笑容渐起,似乎得到了她想要的回答,仍继续问道:那妈妈和奶奶还有我,谁漂亮?

  我哥瞄了一眼侄女,又拿起一粒瓜子坚定的说到:奶奶!

  侄女笑脸瞬间一拉,死死地盯着我哥,幽怨地问道:那里为啥要加我呀?

  我哥再次瞄了一眼侄女,继续剥着瓜子说到:我不想让你妈妈垫底!

  侄女斜眼瞟向我哥,脸上写满了愤怒

  一旁的我,肚子笑疼了!

背景需求

  背景

  项目基于 SpringBoot ,采用 B/S 模式

  主要功能是生成文件,然后将文件上传都 OSS 

  目前通过浏览器可以下载少量文件,但一旦文件过多或文件过大(总体来说就是过大),浏览器下载会很慢,极其容易超时而失败

  需求

  而最近频繁接到产品那边的反馈,说是要下载最近几个月,甚至两三年的某些文件

  总之就是要支持大批量文件的下载

大批量下载实现

  既然业务部门发话了,作为支撑部门,必须得全力以赴,那就整呗

  阿里云oss提供了三种下载文件的方式:简单下载断点续传下载授权给第三方下载

  我们只看简单下载,其他两种方式大家自行去了解

  简单下载方式也分好几种,我们一个个来看

  OSS控制台

  OSS控制台指的就是

  然后按照如下步骤进行文件下载

  但有2点需要注意

  1、不支持通过OSS控制台下载文件夹(包含子目录)

    如果需要下载文件夹(包含子目录),您可以使用ossbrowser、ossutil、SDK、API等方式进行下载

  2、通过OSS控制台可一次批量下载最多100个文件

    最多只能下载100个文件,多不了一点

  很显然这种方式不合适

  1、文件上传到OSS的路径规则导致每个文件都在不同的文件夹下,结果就是只能一个一个文件下载

    效率太低,谁操作谁得骂娘

  2、批量下载的文件数据很容易超过100

  图形化管理工具ossbrowser

  关于 ossbrowser 不做过多介绍,大家直接查阅官网即可:图形化管理工具ossbrowser

  简单点来说, ossbrowser 就是 OSS控制台 的 C 端

  所以也不合适,不合适点和 OSS控制台 方式一样

  阿里云SDK

  目前已实现的少量文件的下载,就是通过此种方式实现的

  产品通过浏览器请求后端,后端通过 阿里云SDK 将文件下载到后端服务器,下载完成之后进行打包,最后将打包文件以流的方式通过浏览器保存到产品电脑的指定文件夹下

  一旦打包文件很大,通过浏览器就很容易超时失败

  那就不通过浏览器呗,后端将打包文件上传到指定的FTP服务器的指定目录下,然后产品去FTP服务器上的指定目录下拿打包文件

  看似可行,但还是有一些不容忽视的不足

  1、需要一台FTP服务器,而且需要对这台FTP服务器进行维护

  2、产品需要从FTP拿打包文件,如果打包文件很大,这个复制过程也很费时

  所以这种方式也不是很合适

  命令行工具ossutil

  关于 ossutil ,命令行工具ossutil已经讲的很详细了

  使用 ossutil 之前,需要先配置它,大家按照配置ossutil配置即可

  需要强调的一点是,如果仅仅只是下载,那么配置的时候用 bucket 的只读账号即可

  本次下载只用到了lscp两个命令,我们来看下这两个命令的使用

   ossutil64 ls oss://qsl-yzb-test/UserData/9088/20230920 

   ossutil64 cp oss://qsl-yzb-test/UserData/9088/20230920/Snipaste_2023-09-25_16-24-39.png D:\qsl-yzb-test\20230920\ 

  我们发现,文件已经下载到 D:\qsl-yzb-test\20230920 目录下

  感觉跟需求很吻合,如果能从单个下载改成批量下载,那么需求就实现了

  一次输入一个 CMD 命令,显然是不行的,需要以 bat 脚本的方式实现多命令的执行,完成文件的下载

  假设我们要下载 1011、9088、9999 这三个资源202308、202309两个月的文件, bat 脚本该如何写?

  我们用两个配置文件来配置资源和月份,类似如下

   bat 的 for 很强大,尤其以 for /f 最强,格式如下

  分别对应文件字符串命令

  我们先用 for /f 来读取两个配置文件

  执行结果如下

  有 2 点需要注意

  1、 cmd 下,变量用一个 % 来表示,比如 %r,示例:

      但是批处理(bat脚本)时,变量需要 %% 来表示,比如 %%r

  2、for命令的形式变量只能是26个字母中的任意一个,同时区分大小写

  配置文件的解析已经实现,接下来需要结合 ossutil 的命令来实现文件的下载了

  一步一步来,我们先结合 ossutil 的 ls 命令获取文件列表

   ossutil64 ls oss://qsl-yzb-test/UserData/9999/202309 结果如下

  我们关注的其实只是 ObjectName 那一列,而 for /f 正好能实现

   for /f "tokens=8 delims= " %p in ('ossutil64 ls oss://qsl-yzb-test/UserData/9999/202309') do echo %p 

  效果如下

   delims=符号列表 :以指定符号列表对字符串进行切割,如果没有指定 delims ,那么默认则以空格键或跳格键作为分隔符号

     for /f "delims= " 和 for /f 是一样的效果

   tokens=n :定点提取第 n 个字符串

     tokens 后可以接多个数字,以逗号隔开,例如: tokens=2,5,8 

   delims 进行切割, tokens 获取切割后指定位置的字符串

  放进 bat 脚本

  执行结果如下

  我们需要的是文件列表,不需要关注目录,那如何过滤掉目录了?

   ossutil 的 ls 命令正好有 --include 参数能实现过滤

  执行结果如下

  oss文件路径已经获取到,接下来就是结合 cp 命令进行下载了

  执行后, D:\qsl-yzb-test 目录下文件如下

  离成功还差一步之遥,需要将文件按日期进行划分,比如 20230921 这天的所有文件全部放到 20230921 这个目录下

  oss文件路径是有规则的,具体文件名的上一级目录就是日期目录,所以我们可以从oss路径中截取日期目录, for /f 正好能实现

  执行后, D:\qsl-yzb-test 目录内容如下

  自此,算是大功告成了

  但如果能手动指定下载目录就好了(下载目录作为 bat 参数)

  这个很简单,直接上代码

  完整脚本代码

@ECHO OFF
rem 字符编码设置成UTF-8编码,防止中文乱码
chcp 65001

rem %1 下载目录
if "%1"=="" (
    echo "请指定下载目录,类似 D:\qsl-yzb-test"
    goto :eof
)

for /f %%r in (resource_config.txt) do (
    for /f %%m in (month_config.txt) do (
        for /f "tokens=8 delims= " %%p in ('ossutil64 ls oss://qsl-yzb-test/UserData/%%r/%%m --include *.*') do (
            for /f "tokens=5 delims=/" %%d in ("%%p") do (
                rem -f表示同名覆盖
                ossutil64 cp %%p %1\%%d\ -f
            )
        )
    )
)
View Code

  REST API

  自定义要求较高的情况可以考虑这种方式,感兴趣的可以去看官方说明

总结

  1、 ossutil 提供了很多命令,实现需求之前可以先翻一翻官方文档说明

  2、 cmd 和 bat 的变量命名是有区别的,大家一定要注意

  3、 for 很强大, for /f 强大的最突出

参考

  批处理for语句从入门到精通

标签:文件,bat,不好玩,%%,OSS,yzb,qsl,ossutil,下载
From: https://www.cnblogs.com/youzhibing/p/17787414.html

相关文章

  • java后置运行bat
    后置@echooffcdD:\server\gp12\alarmJavad:start/Bjavaw-jar-Xms128m-Xmx1024mpigx-gp12-biz.jar前置cdD:\server\gp12\alarmJavajava-jar-Xms128m-Xmx1024mpigx-gp12-biz.jar......
  • 【mysql】获取某个表所有列名【mybatis】
    方法1:[仅指定表名]selectCOLUMN_NAMEfrominformation_schema.COLUMNSwheretable_name='your-table-name'; 方法2:[指定表名+数据库名]selectCOLUMN_NAMEfrominformation_schema.COLUMNSwheretable_name='your-table-name'andtable_schema='your-DB......
  • SpringBoot系列之MyBatis Plus自动填充实现
    系列博客专栏:SpringBoot2.0系列博客专栏开发环境JDK1.8SpringBoot2.2.1Maven3.2+Mysql5.7.36开发工具IntelliJIDEAsmartGit项目场景在项目中经常会遇到需要自动填充数据的情况,比如新增一个DO类,里面可能会有id、create_time、modify_time、create_u......
  • [论文阅读] Mean-Shifted Contrastive Loss for Anomaly Detection
    Mean-ShiftedContrastiveLossforAnomalyDetectionAbstract这篇文章探讨了异常检测领域的一个关键问题,即如何通过使用预训练特征来提高异常检测性能。研究者首先介绍了异常检测的背景和现有方法,指出了使用自监督学习和外部数据集预训练特征的潜力。然后,他们详细分析了标准对......
  • MyBatis了解
    MyBatis了解MyBatis是什么?MyBatis是支持定制化SQL、存储过程以及高级映射的优秀的持久层框架MyBatis避免了几乎所有的JDBC代码和手动设置参数以及获取结果集MyBatis可以使用简单的XML或注解用于配置和原始映射,将接口和Java的POJO(PlainOldJavaObjects,普通的Java对象)映射......
  • Mybatis中 collection 和 association 标签 的区别
    版权声明:本文为CSDN博主「时夏゛」的原创文章,遵循CC4.0BY-SA版权协议,转载请附上原文出处链接及本声明。原文链接:https://blog.csdn.net/XikYu/article/details/132761255<collection>和<association>是MyBatis中用于定义映射关系的标签,它们的区别如下:目标对象类型:<colle......
  • Springmvc和mybatis和spring的整合
    一.springmvc工作原理springmvc常用的组件为SpingMVC的常用组件:1)DispatcherServlet是一种前端控制器,由框架提供。作用:统一处理请求和响应。除此之外还是整个流程控制的中心,由DispatcherServlet来调用其他组件,处理用户的请求2)HandlerMapping处理器映射器,由框架提供。作用:......
  • The Last Battle —— 2023~2024 赛季考场代码合辑
    \[\Huge\mathfrak{CSP-S2023}\]\[{\color{orange}\textrm{340}}\textrm{/400}\]\(\textrm{A}\;\text{密码锁}\)\({\color{limegreen}\textrm{100}}\textrm{/100}\)\(\textrm{Wedecide.}\)\(\textrm{Wechoose.}\)\(\textrm{Aswedeci......
  • All Possible Digits
    here单调性:多加几次,出现的数不会变少,肯定可以二分。最多操作\(p-1\)次,也就是最多进位一次。而且最多只会进位一次,对于最后一位在加的过程中出现的值,直接用式子算,然后为了统计出现的数的次数,在其他位的数,如果在最后一位变化的范围里,就不应该加1。但是题解又有不用二分的做法…......
  • 大模型训练中Loss出现NaN的解决策略
    在深度学习中,模型训练时的loss值通常是评估模型性能的重要指标。然而,有时候在训练过程中,loss值可能会出现nan,这可能会导致训练中断或者模型性能下降。本文将探讨导致loss出现nan的原因,以及相应的解决方法。一、原因分析梯度爆炸梯度爆炸是导致loss出现nan的一个常见原因。当梯度在......