SpringBoot项目resources下指定目录的所有文件下载到Centos服务器上,浏览器访问API后资源包直接下载本地磁盘,Java删除linux文件,zip文件打包
项目场景:
公司产品后台服务版本升级之增量资源包打包功能开发:每一次版本升级的增量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文件打包相关推荐
- Linux常用命令下,以及再CentOS7下搭建apache网站服务,以及同一服务器上搭建第二个网站
Linux常用命令下,以及再CentOS7下搭建apache网站服务,以及同一服务器上搭建第二个网站 Linux 常用命令ls -l 以长格式显示-a 显示.. 和 .-A 不显示 . 和 ..-d ...
- SpringBoot项目多环境指定环境打包(小白必看)
文章目录 指定环境打包 方式一: 方式二: 开心一刻 指定环境打包 现在的SpringBoot项目往往是有多个环境的,那么如何动态的指定环境打包呢? 下面介绍两个方式: 两种方式,本质上没有什么区别, ...
- SpringBoot读取Resources下文件
问题: 需要读取resources下的文件,文件格式不定,这里以txt为例,主要说明路径问题: 一.使用项目内路径读取,该路径只在开发工具中显示,类似:src/main/resources/resou ...
- java删除Linux目录下的文件夹
在java程序中删除Linux目录下的文件夹主要步骤如下: String path = "/home/deledir";//文件夹路径 String[] cmd = new Str ...
- 删除 linux的ln文件夹,linux下添加链接与删除链接(ln命令的用法)
添加链接使用ln命令 用法: #ln --help 用法:ln [选项]... 目标 [链接名] 或:ln [选项]... 目标... 目录 或:ln [选项]... --target-directo ...
- centos下安装PHP的IDE,如何在 CentOS 8 上安装和使用 PHP 编辑器
omposer是 PHP 的依赖管理器(如 npm 是节点.js pip是 Python). Composer 将提取项目所依赖的所有必需的 PHP 包,并为此管理它们.它用于所有现代 PHP 框架和 ...
- nginx 跨服务器显示图片,centos6.6下nginx配置远程服务器上图片访问
将远程图片服务器挂载到Nginx所在服务器上,然后在Nginx上配置访问. 步骤 两台服务器信息如下: 服务器名称 服务器IP 共享目录 服务器说明 A 10.100.1.10 /mnt/data N ...
- 基于librtmp的安卓小项目:投屏摄像头视频:推流rtmp到服务器上并显示在其它设备上(比如电脑或者其它直播平台)
首先这个项目并未实现音频的传输,后面有时间再实现音频的传输后更新博文.这里如果是自己部署流媒体服务器,可以参考搭建nginx的相关博文,这里需要注意的是如果是搭建在linux系统下面,那么网络最好选用 ...
- linux中zip文件编码错误,解决linux下zip文件解压乱码问题
原标题:解决linux下zip文件解压乱码问题 解决linux下zip文件解压乱码问题 原因 由于zip格式并没有指定编码格式,Windows下生成的zip文件中的编码是GBK/GB2312等,因此, ...
- 记录第一次成功将vue项目打包并部署到centos云服务器上并访问(包含多个vue项目部署nginx配置说明)
文章目录 准备 vue项目打包 配置服务器 使用xshell 使用xftp 当项目更新时操作 小结 准备 vscode:用于打包vue项目(需要提前安装好node与npm,推荐使用mvn管理node, ...
最新文章
- 用xlg.tel来管理自己
- pandas将某一列变为索引_Pandas 基础语法入门
- Delphi 7下使用VT实现树型列表结合控件
- CAN总线的初步认识
- 比较常用的25条Excel技巧
- Spring Boot中使用@Async实现异步调用
- 天气预报HTML代码
- Python-----包和日志的使用
- 吸猫就吸Tomcat之Pipeline-Valve巧妙设计
- 发那科机器人仿真软件FANUCROBOGUIDE打开机器备份
- 药品计算机系统操作知识培训,新版GSP:计算机系统专业知识培训测试题(6)
- 电大考试计算机应用基础考试试题,电大计算机应用基础网络教育统考考试(2013真题卷)...
- 如何看待阿里云成立新零售事业部?
- 统计学习导论之R语言应用(三):线性回归R语言代码实战
- 物联网卡的分类有哪些
- ProgressBar进度条(圆形进度条|水平进度条)
- php命名空间namespace自动载入
- matlab进行动力吸振器设计,基于有限元法的动力吸振器设计研究
- 图片型pdf转文本文档
- Django2 Django MTV模板