项目场景:

公司产品后台服务版本升级之增量资源包打包功能开发:每一次版本升级的增量sql(SpringBoot项目的resources下)增量sql相对应的资源(在资源云服务器上:Centos7系统)打包下载接口。

涉及知识点:

  • 浏览器访问API,资源包直接下载本地磁盘
  • 访问resources下指定目录的文件
  • Java删除Linux文件
  • Zip文件打包(提供ZipUtil)

业务:运维人员登录后台系统点击资源打包功能,下载压缩的资源zip包上传到另一个云服务器(专门用于版本升级的),用户的本地服务器可以定时检测同步是否有新版本,从而下载对应的资源包,话不多说,上代码:


Controller层:

@Api(tags = "版本与license Controller")
@RequestMapping("/version")
@RestController
public class VersionController extends BaseController {@Resourceprivate VersionService versionService;   @ApiOperation(value = "生成资源压缩包")@GetMapping("/admin/generateResourceZip")@SysLog(value = "生成压缩资源包", isEdit = false)public void generateResourceZip(HttpServletResponse response) throws Exception {String resourcePath = versionService.generateResourceZip();String filename = URLEncoder.encode(resourcePath.substring(resourcePath.lastIndexOf("/")+1), "UTF-8");response.setContentType("application/x-download");response.setHeader("Content-Disposition", "attachment;filename=" + filename);//浏览器上提示下载时默认的文件名try (ServletOutputStream out = response.getOutputStream();InputStream stream = new FileInputStream(resourcePath)){//读取服务器上的文件byte buff[] = new byte[1024];int length = 0;while ((length = stream.read(buff)) > 0) {out.write(buff,0,length);}stream.close();out.close();out.flush();} catch (IOException e) {e.printStackTrace();}}
}

Service层:

/*** @Author: yz* @Date 14:42 2023/1/7* @Param []* @return 版本资源打包功能*/@Overridepublic String generateResourceZip() throws Exception {//找到对应的增量sql文件//加载资源文件String path = Constants.RESOURCE_SQL_PATH;final Resource[] resources = new PathMatchingResourcePatternResolver().getResources(ResourceUtils.CLASSPATH_URL_PREFIX + path);log.info("开始扫描增量sql");//存储在fastdfs上的路径集合List<String> fastdfsList = new ArrayList<>();//存储在nginx下xxa目录下的路径集合List<String> nginxXxaList = new ArrayList<>();//存储在nginx下xxb目录下的路径集合List<String> nginxXxbList = new ArrayList<>();//存储在nginx下xxc目录下的路径集合List<String> nginxXxcList = new ArrayList<>();//存储在nginx下xxd目录下的路径集合List<String> nginxXxdList = new ArrayList<>();//读取增量sql文件的资源path内容for (int i = 0; i < resources.length; i++) {Resource resource = resources[i];// 遍历文件内容StringBuffer script = new StringBuffer();try(InputStreamReader isr = new InputStreamReader(resource.getInputStream(), StandardCharsets.UTF_8);BufferedReader bufferReader = new BufferedReader(isr)) {String tempString;while ((tempString = bufferReader.readLine()) != null) {script.append(tempString).append("\n");}} catch (IOException e) {e.printStackTrace();}String content = script.toString();//判断资源存储于fastdfs、nginx下xxd、xxb、xxa、xxc下String[] fsatdfsSplit = content.split(Constants.FASTDFS_PATH);String[] xxaSplit = content.split(Constants.SPECIAL_INTERACTION_PATH);String[] xxbSplit = content.split(Constants.EXAM_INTERACTION_PATH);String[] xxcSplit = content.split(Constants.INTERACTION_UPLOAD_PATH);String[] xxdSplit = content.split(Constants.INTERACTION_ASSESS_PATH);if(fsatdfsSplit.length>1){fastdfsPackage(content,fastdfsList);}if(xxaSplit.length>1){for (int j = 0; j < xxaSplit.length; j++) {if(j>0){nginxXxaList.add("/html/"+Constants.SPECIAL_INTERACTION_PATH+xxaSplit[j].substring(0,xxaSplit[j].indexOf("\'")));}}}if(xxbSplit.length>1){for (int j = 0; j < xxbSplit.length; j++) {if(j>0){nginxXxbList.add("/html/"+Constants.EXAM_INTERACTION_PATH+xxbSplit[j].substring(0,xxbSplit[j].indexOf("\'")));}}}if(xxcSplit.length>1){for (int j = 0; j < xxcSplit.length; j++) {if(j>0){nginxXxcList.add("/html/"+Constants.INTERACTION_UPLOAD_PATH+xxcSplit[j].substring(0,xxcSplit[j].indexOf("\'")-1));}}}if(xxdSplit.length>1){for (int j = 0; j < xxdSplit.length; j++) {if(j>0){nginxXxdList.add("/html/"+Constants.INTERACTION_ASSESS_PATH+xxdSplit[j].substring(0,xxdSplit[j].indexOf("\'")-1));}}}}//根据path内容cp资源到服务器的mnt目录下(条件判断必须是linux环境下)//获取当前环境String osName = System.getProperty("os.name");String fileUploadPath;if (!osName.startsWith("Windows")) {//linux,创建文件夹汇总所有版本资源fileUploadPath= Constants.VERSION_PATH+"/";File uploadFile = new File(fileUploadPath);if (uploadFile.exists()) {//需要删除原先的resources资源文件夹String rmDirCommond = "rm -rf "+Constants.VERSION_PATH;Runtime.getRuntime().exec(rmDirCommond);log.info("删除原先的resources资源文件夹成功");}uploadFile.mkdirs();//复制fastdfs的新增资源if(fastdfsList.size()>0){FastDFSClientUtil fastDFSClientUtil = new FastDFSClientUtil();for (int i = 0; i < fastdfsList.size(); i++) {String targetPath = fileUploadPath+"data"+fastdfsList.get(i);String fastDirPath = targetPath.substring(0,targetPath.lastIndexOf("/"));log.info("先创建文件目录:"+fastDirPath);log.info("目标文件目录:"+targetPath);File fastDir = new File(fastDirPath);fastDir.mkdirs();File fastFile = new File(targetPath);fastFile.createNewFile();int downFlag = fastDFSClientUtil.download_file(Constants.FASTDFS_PATH+fastdfsList.get(i),new BufferedOutputStream(new FileOutputStream(targetPath)));log.info("第"+(i+1)+"个文件的下载结果为:" + (downFlag == 0 ? "下载文件成功" : "下载文件失败"));}}//复制nginx下xxd、xxb、xxa、xxc下版本新增的交互动画资源(文件夹的资源形式)copyNginxFolder(nginxXxdList, fileUploadPath);copyNginxFolder(nginxXxbList, fileUploadPath);copyNginxFolder(nginxXxaList, fileUploadPath);copyNginxFolder(nginxXxcList, fileUploadPath);} else {throw new BusinessException("请发布linux系统后打包版本资源");}//打包shell脚本final Resource[] shellResources = new PathMatchingResourcePatternResolver().getResources(ResourceUtils.CLASSPATH_URL_PREFIX + Constants.RESOURCE_SHELL_PATH);String shellFolderPath;//linux,创建文件夹汇总所有版本资源shellFolderPath = Constants.VERSION_PATH + "/shell/";File shellFolderFile = new File(shellFolderPath);shellFolderFile.mkdirs();//复制shell文件log.info("复制shell文件...");for (int n = 0; n < shellResources.length; n++) {final Resource shellResource = shellResources[n];// 遍历文件内容StringBuffer shellScript = new StringBuffer();try(InputStreamReader isr = new InputStreamReader(shellResource.getInputStream(), StandardCharsets.UTF_8);BufferedReader bufferReader = new BufferedReader(isr)) {String tempString;while ((tempString = bufferReader.readLine()) != null) {shellScript.append(tempString).append("\n");}} catch (IOException e) {e.printStackTrace();}String shellContent = shellScript.toString();String name = shellResource.getFilename();File dest = new File(shellFolderPath + name);dest.createNewFile();FileWriter fw=new FileWriter(dest,true);fw.write(shellContent);fw.close();}//压缩命令zip FileName.zip DirName压缩资源目录log.info("开始资源压缩打包...");FileOutputStream fos1 = new FileOutputStream(Constants.VERSION_NAME);ZipUtil.zip(Constants.VERSION_PATH, fos1);log.info("开始资源压缩打包成功");return Constants.VERSION_NAME;}/*** @Author: yz* @Date 19:14 2023/1/5* @Param [list, fileUploadPath]* @return 复制nginx目录下的资源文件夹*/private static void copyNginxFolder(List<String> list, String fileUploadPath) throws Exception {if(list.size()>0){for (int i = 0; i < list.size(); i++) {String targetPath = fileUploadPath+"nginx"+list.get(i);String sourcePath = Constants.NGINX_DOWNLOAD_PATH+list.get(i);log.info("nginx原资源文件路径:"+sourcePath);copyFolder(sourcePath,targetPath);}}}/*** @Author: yz* @Date 13:26 2023/1/5* @Param [file, list]* @return fastdfs解析文件封装函数*/public static void fastdfsPackage(String content,List<String> list) throws IOException {String[] split = content.split("XXXXXX");for (int j = 0; j < split.length; j++) {if(j>0){list.add(split[j].substring(0,split[j].indexOf("\'")));}}}/*** @Author: yz* @Date 13:26 2023/1/5* 复制文件夹(使用缓冲字节流)* @param sourcePath 源文件夹路径* @param targetPath 目标文件夹路径*/public static void copyFolder(String sourcePath,String targetPath) throws Exception{//源文件夹路径File sourceFile = new File(sourcePath);//目标文件夹路径File targetFile = new File(targetPath);if(!sourceFile.exists()){log.info("源文件夹不存在:"+sourcePath);return;//throw new Exception("文件夹不存在");}if(!sourceFile.isDirectory()){throw new Exception("源文件夹不是目录");}if(!targetFile.exists()){targetFile.mkdirs();}if(!targetFile.isDirectory()){throw new Exception("目标文件夹不是目录");}File[] files = sourceFile.listFiles();if(files == null || files.length == 0){return;}for(File file : files){//文件要移动的路径String movePath = targetFile+File.separator+file.getName();if(file.isDirectory()){//如果是目录则递归调用copyFolder(file.getAbsolutePath(),movePath);}else {//如果是文件则复制文件BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(movePath));byte[] b = new byte[1024];int temp = 0;while((temp = in.read(b)) != -1){out.write(b,0,temp);}out.close();in.close();}}}

ZipUtil类:

@Slf4j
@RestController
public class ZipUtil {/*** 压缩文件夹到指定输出流中,可以是本地文件输出流,也可以是web响应下载流** @param srcDir       源文件夹* @param outputStream 压缩后文件的输出流* @throws IOException IO异常,抛出给调用者处理* @auther CZW*/public static void zip(String srcDir, OutputStream outputStream) throws IOException {try (BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);ArchiveOutputStream out = new ZipArchiveOutputStream(bufferedOutputStream);) {Path start = Paths.get(srcDir);Files.walkFileTree(start, new SimpleFileVisitor<Path>() {@Overridepublic FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {ArchiveEntry entry = new ZipArchiveEntry(dir.toFile(), start.relativize(dir).toString());out.putArchiveEntry(entry);out.closeArchiveEntry();return super.preVisitDirectory(dir, attrs);}@Overridepublic FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {try (InputStream input = new FileInputStream(file.toFile())) {ArchiveEntry entry = new ZipArchiveEntry(file.toFile(), start.relativize(file).toString());out.putArchiveEntry(entry);IOUtils.copy(input, out);out.closeArchiveEntry();}return super.visitFile(file, attrs);}});}}/*** 解压zip文件到指定文件夹** @param zipFileName 源zip文件路径* @param destDir     解压后输出路径* @throws IOException IO异常,抛出给调用者处理* @auther CZW*/public static void unzip(String zipFileName, String destDir) throws IOException {try (InputStream inputStream = new FileInputStream(zipFileName);) {unzip(inputStream, destDir);}}/*** 从输入流中获取zip文件,并解压到指定文件夹** @param inputStream zip文件输入流,可以是本地文件输入流,也可以是web请求上传流* @param destDir     解压后输出路径* @throws IOException IO异常,抛出给调用者处理* @auther CZW*/public static void unzip(InputStream inputStream, String destDir) throws IOException {try (BufferedInputStream bufferedInputStream = new BufferedInputStream(inputStream);ArchiveInputStream in = new ZipArchiveInputStream(bufferedInputStream);) {ArchiveEntry entry;while (Objects.nonNull(entry = in.getNextEntry())) {if (in.canReadEntryData(entry)) {File file = Paths.get(destDir, entry.getName()).toFile();if (entry.isDirectory()) {if (!file.exists()) {file.mkdirs();}} else {try (OutputStream out = new FileOutputStream(file);) {IOUtils.copy(in, out);}}} else {log.info(entry.getName());}}}}}

 结果:


总结:

增量sql截取存储资源对应的path,找到资源服务器下对应的资源下载到服务器指定一个目录下,最后web端访问接口下载到本地


结束语:

-----忧伤没有成本意识,激动没有判断能力,疲惫让人失去主见(旅游乱买,半夜买东西),结论:重要决策一定要平静的时候。

SpringBoot项目resources下指定目录的所有文件下载到Centos服务器上,浏览器访问API后资源包直接下载本地磁盘,Java删除linux文件,zip文件打包相关推荐

  1. Linux常用命令下,以及再CentOS7下搭建apache网站服务,以及同一服务器上搭建第二个网站

    Linux常用命令下,以及再CentOS7下搭建apache网站服务,以及同一服务器上搭建第二个网站 Linux 常用命令ls -l 以长格式显示-a 显示.. 和 .-A 不显示 . 和 ..-d ...

  2. SpringBoot项目多环境指定环境打包(小白必看)

    文章目录 指定环境打包 方式一: 方式二: 开心一刻 指定环境打包 现在的SpringBoot项目往往是有多个环境的,那么如何动态的指定环境打包呢? 下面介绍两个方式: 两种方式,本质上没有什么区别, ...

  3. SpringBoot读取Resources下文件

    问题: 需要读取resources下的文件,文件格式不定,这里以txt为例,主要说明路径问题: 一.使用项目内路径读取,该路径只在开发工具中显示,类似:src/main/resources/resou ...

  4. java删除Linux目录下的文件夹

    在java程序中删除Linux目录下的文件夹主要步骤如下: String path = "/home/deledir";//文件夹路径 String[] cmd = new Str ...

  5. 删除 linux的ln文件夹,linux下添加链接与删除链接(ln命令的用法)

    添加链接使用ln命令 用法: #ln --help 用法:ln [选项]... 目标 [链接名] 或:ln [选项]... 目标... 目录 或:ln [选项]... --target-directo ...

  6. centos下安装PHP的IDE,如何在 CentOS 8 上安装和使用 PHP 编辑器

    omposer是 PHP 的依赖管理器(如 npm 是节点.js pip是 Python). Composer 将提取项目所依赖的所有必需的 PHP 包,并为此管理它们.它用于所有现代 PHP 框架和 ...

  7. nginx 跨服务器显示图片,centos6.6下nginx配置远程服务器上图片访问

    将远程图片服务器挂载到Nginx所在服务器上,然后在Nginx上配置访问. 步骤 两台服务器信息如下: 服务器名称 服务器IP 共享目录 服务器说明 A 10.100.1.10 /mnt/data N ...

  8. 基于librtmp的安卓小项目:投屏摄像头视频:推流rtmp到服务器上并显示在其它设备上(比如电脑或者其它直播平台)

    首先这个项目并未实现音频的传输,后面有时间再实现音频的传输后更新博文.这里如果是自己部署流媒体服务器,可以参考搭建nginx的相关博文,这里需要注意的是如果是搭建在linux系统下面,那么网络最好选用 ...

  9. linux中zip文件编码错误,解决linux下zip文件解压乱码问题

    原标题:解决linux下zip文件解压乱码问题 解决linux下zip文件解压乱码问题 原因 由于zip格式并没有指定编码格式,Windows下生成的zip文件中的编码是GBK/GB2312等,因此, ...

  10. 记录第一次成功将vue项目打包并部署到centos云服务器上并访问(包含多个vue项目部署nginx配置说明)

    文章目录 准备 vue项目打包 配置服务器 使用xshell 使用xftp 当项目更新时操作 小结 准备 vscode:用于打包vue项目(需要提前安装好node与npm,推荐使用mvn管理node, ...

最新文章

  1. 用xlg.tel来管理自己
  2. pandas将某一列变为索引_Pandas 基础语法入门
  3. Delphi 7下使用VT实现树型列表结合控件
  4. CAN总线的初步认识
  5. 比较常用的25条Excel技巧
  6. Spring Boot中使用@Async实现异步调用
  7. 天气预报HTML代码
  8. Python-----包和日志的使用
  9. 吸猫就吸Tomcat之Pipeline-Valve巧妙设计
  10. 发那科机器人仿真软件FANUCROBOGUIDE打开机器备份
  11. 药品计算机系统操作知识培训,新版GSP:计算机系统专业知识培训测试题(6)
  12. 电大考试计算机应用基础考试试题,电大计算机应用基础网络教育统考考试(2013真题卷)...
  13. 如何看待阿里云成立新零售事业部?
  14. 统计学习导论之R语言应用(三):线性回归R语言代码实战
  15. 物联网卡的分类有哪些
  16. ProgressBar进度条(圆形进度条|水平进度条)
  17. php命名空间namespace自动载入
  18. matlab进行动力吸振器设计,基于有限元法的动力吸振器设计研究
  19. 图片型pdf转文本文档
  20. Django2 Django MTV模板

热门文章

  1. 世界为什么是五彩缤纷
  2. 什么?学了C语言还不会表白,下面的多彩小心心快去拿给那个她吧
  3. nav-tage、vue3.0顶部历史浏览记录代码实现 vuex + el + vue3.0
  4. 常见排序算法原理及java实现
  5. 迷宫小游戏Java实现
  6. 设置Cookie的生命周期
  7. 洛谷【P1195】口袋的天空
  8. 南京信息工程大学计算机考研怎么样,南京信息工程大学就业怎么样,考研好不好?...
  9. solidworks出专利图小技巧
  10. java画矩形代码_Java以一种方式绘制矩形