【SpringBoot项目实战】图片压缩包上传、解压、存储等等一套流程教学

2023-11-12


前言

之前一直用的zip4j来对压缩包进行操作,但后来发现Hutool里面也有ZipUtil,ZipUtil是对 java.util.zip 做工具化封装

操作起来大同小异,改成了Hutool的ZipUtil,这样就少引用了一个依赖。

相关工具:Hutool 压缩工具-ZipUtil (点击跳转)


一、压缩包上传

1、接口实现

在Class上加上**@RestController** 标注此类为控制器类

@PostMapping(“/upload”) 标注此方法访问路径为"/upload",访问方法是POST

这边接口接收的内容类型 Content-Typemultipart/form-data,这边接收时会自行根据参数进行判断

@RequestParam(“zipFile”) 注解用来获取 zipFile 字段中对应的内容

首先,先实现一个用于上传文件的post接口,代码如下:

@RestController
public class Controller {

	/**
    * 压缩包文件上传
    *
    * @param zipFile 压缩包文件
    * @return R 返回实体类
    */
    @PostMapping("/upload")
    public R upload(@RequestParam("zipFile") MultipartFile zipFile) {
    	//TODO
    	return R.success();
    }
}

这边上传URL默认为:http://127.0.0.1:8080/upload

2、获取压缩包的文件名和文件路径

这边使用 @Value 注解获取配置文件 application.yml 的上传路径 config.uploadPath 的值

在Class上别忘了加上 @Component 注解进行组件扫描,这样才能获取到配置文件中的上传路径 uploadPath

上传文件的接收参数类型为 MultipartFile

代码如下:

//组件扫描注解,用于获取配置文件内容
@Component
@RestController
public class Controller {
	
	//获取配置文件中的文件上传物理路径,例:C:/
    @Value("${config.uploadPath}")
    private String uploadPath;

	/**
    * 压缩包文件上传
    *
    * @param zipFile 压缩包文件
    * @return R 返回实体类
    */
    @PostMapping("/upload")
    public R multiFace(@RequestParam("zipFile") MultipartFile zipFile) {
    	//获取文件全名
    	String fileName = zipFile.getOriginalFilename();
    	//解压目标文件夹对象(压缩文件解压到此文件夹中)
    	File extractFolder = new File(uploadPath + "extract/");
		//压缩包存储目标文件对象
        File destFile = new File(uploadPath + fileName);
        //文件上传路径对象
        File fileDirectory = new File(uploadPath);
        //当上传路径不存在时,生成上传路径
        if (!fileDirectory.exists()) {
            fileDirectory.mkdirs();
        }
        //TODO
    	return R.success();
    }
}

二、压缩包解压并保存

1、处理压缩包文件方法

解压缩步骤:

  1. 将上传的压缩包保存至文件夹
  2. 解压文件夹中的压缩包到指定目录
  3. 获取该目录中所有文件的文件数组对象

代码如下:

    /**
     * 处理压缩包文件
     *
     * @param zipFile       上传压缩包
     * @param destFile      指定压缩包路径
     * @param extractFolder 解压后文件夹
     * @return R 返回实体类
     */
    private R dealZip(MultipartFile zipFile, File destFile, File extractFolder) {
    	//判断解压后文件夹是否存在
        if (!extractFolder.exists()) {
        	//不存在就创建
            extractFolder.mkdirs();
        }
        try {
        	//步骤1、把上传的压缩包文件保存到指定压缩包路径
            zipFile.transferTo(destFile);
        } catch (IOException e) {
        	//运行报错直接返回错误信息
            return R.failed(e.getMessage());
        }
        //步骤2、调用Hutool的ZipUtil压缩工具类的unzip方法来进行对压缩包文件的解压,解压到指定目录
        ZipUtil.unzip(destFile, extractFolder);
        //解压缩完删除原文件(可不删)
        destFile.delete();
        //步骤3、获取解压后目录下所有的文件
        File[] images = extractFolder.listFiles();
        //这边对获取到的文件数组进行判空校验
        if (images == null || images.length == 0) {
        	//不存在就把压缩文件夹删除(可不删)
            extractFolder.delete();
            return failed("上传失败,压缩包为空");
        }
        //错误文件集合
        List<String> nameList = new ArrayList<>();
        //这边简单做个jpg图片校验,单个文件全名中不包含jpg的文件添加到错误集合中
        stream(images).forEach(image -> {
            if (!image.getName().contains("jpg")) {
                nameList.add(image.getName());
            }
        });
        //错误集合存在数据就返回错误的文件名集合
        if (nameList.size() > 0) {
        	//存在错误图片就把压缩文件夹删除(可不删)
            extractFolder.delete();
            return failed("压缩包文件错误,错误文件如下:" + nameList + ",请修改后再上传");
        }
        //错误集合长度为0时返回解压后文件数组对象
        return success(images);
    }

2、接口中实现处理压缩包

代码如下:

//组件扫描注解,用于获取配置文件内容
@Component
@RestController
public class Controller {
	
	//获取配置文件中的文件上传物理路径,例:C:/
    @Value("${config.uploadPath}")
    private String uploadPath;

    //Service层
    @Resource
    private Service service;
	
	/**
    * 压缩包文件上传
    *
    * @param zipFile 压缩包文件
    * @return R 返回实体类
    */
    @PostMapping("/upload")
    public R multiFace(@RequestParam("zipFile") MultipartFile zipFile) {
    	//获取文件全名
    	String fileName = zipFile.getOriginalFilename();
    	//解压目标文件夹对象(压缩文件解压到此文件夹中)
    	File extractFolder = new File(uploadPath + "extract/");
		//压缩包存储目标文件对象
        File destFile = new File(uploadPath + fileName);
        //文件上传路径对象
        File fileDirectory = new File(uploadPath);
        //当上传路径不存在时,生成上传路径
        if (!fileDirectory.exists()) {
            fileDirectory.mkdirs();
        }
        //调用上面【处理压缩包文件方法】得到返回结果
		R zipResult = dealZip(zipFile, destFile, extractFolder);
		//失败就返回错误信息
        if (FAIL_CODE == zipResult.getCode()) {
            return zipResult;
        }
        //获取【处理压缩包文件方法】中返回的图片文件数组对象
        File[] images = (File[]) zipResult.getData();
        //实体类集合
        List<Entity> entities = new ArrayList<>();
        //这边使用stream对图片文件数组对象进行遍历
        stream(images).forEach(image -> {
        	//TODO 这边可以做其他的处理
        	//这边简单的获取了照片名字的前缀作为id
            String id = image.getName().split("\\.")[0];
            //通过数据库找找此id的信息
            Entity entity = service.getById(id);
            if (entity != null) {
            	//存在此条信息就把此图片拷贝到上传目录中,这边用到Hutool的FileUtil文件工具类的copy文件拷贝方法
                FileUtil.copy(image, new File(uploadPath + image.getName()), true);
                //存在就添加进实体类集合
                entities.add(entity);
            }
        });
        //实体类为空代表在数据库中没有找到对应id的信息
        if (entities.size() == 0) {
        	//删除解压缩目录(可不删)
            extractFolder.delete();
            return failed("压缩包内图片无匹配信息");
        }
        //删除解压缩目录(可不删)
        extractFolder.delete();
        //最后数据库根据id更新所有集合实体类的信息
        return service.updateBatchById(entities) ? 
        	success("压缩包上传成功") : 
        	failed("压缩包上传失败");
    }
}

三、总结

这边项目主要应用是上传人脸的照片压缩包

解压缩后,根据照片的名称前缀为人员id来进行保存

压缩包遍历中可以按照业务需求进行文件区分再进行其他操作

这些年程序员生涯,发现网上一些解决方案很少有完整的

都是零零散散的,查起来特别费劲,所以自己写解决方案会尽量要求写完整

方便自己也方便别人

感谢您能看完本篇内容

在这里插入图片描述

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【SpringBoot项目实战】图片压缩包上传、解压、存储等等一套流程教学 的相关文章

  • Java中反射是如何实现的?

    Java 7 语言规范很早就指出 本规范没有详细描述反射 我只是想知道 反射在Java中是如何实现的 我不是问它是如何使用的 我知道可能没有我正在寻找的具体答案 但任何信息将不胜感激 我在 Stackoverflow 上发现了这个 关于 C
  • 如何找到给定字符串的最长重复子串

    我是java新手 我被分配寻找字符串的最长子字符串 我在网上研究 似乎解决这个问题的好方法是实现后缀树 请告诉我如何做到这一点或者您是否有任何其他解决方案 请记住 这应该是在 Java 知识水平较低的情况下完成的 提前致谢 附 测试仪字符串
  • JAXb、Hibernate 和 beans

    目前我正在开发一个使用 Spring Web 服务 hibernate 和 JAXb 的项目 1 我已经使用IDE hibernate代码生成 生成了hibernate bean 2 另外 我已经使用maven编译器生成了jaxb bean
  • 操作错误不会显示在 JSP 上

    我尝试在 Action 类中添加操作错误并将其打印在 JSP 页面上 当发生异常时 它将进入 catch 块并在控制台中打印 插入异常时出错 请联系管理员 在 catch 块中 我添加了它addActionError 我尝试在jsp页面中打
  • 十进制到八进制的转换[重复]

    这个问题在这里已经有答案了 可能的重复 十进制转换错误 https stackoverflow com questions 13142977 decimal conversion error 我正在为一个类编写一个程序 并且在计算如何将八进
  • 在两个活动之间传输数据[重复]

    这个问题在这里已经有答案了 我正在尝试在两个不同的活动之间发送和接收数据 我在这个网站上看到了一些其他问题 但没有任何问题涉及保留头等舱的状态 例如 如果我想从 A 类发送一个整数 X 到 B 类 然后对整数 X 进行一些操作 然后将其发送
  • getResourceAsStream() 可以找到 jar 文件之外的文件吗?

    我正在开发一个应用程序 该应用程序使用一个加载配置文件的库 InputStream in getClass getResourceAsStream resource 然后我的应用程序打包在一个 jar文件 如果resource是在里面 ja
  • 总是使用 Final?

    我读过 将某些东西做成最终的 然后在循环中使用它会带来更好的性能 但这对一切都有好处吗 我有很多地方没有循环 但我将 Final 添加到局部变量中 它会使速度变慢还是仍然很好 还有一些地方我有一个全局变量final 例如android Pa
  • Java Integer CompareTo() - 为什么使用比较与减法?

    我发现java lang Integer实施compareTo方法如下 public int compareTo Integer anotherInteger int thisVal this value int anotherVal an
  • 如何在 javadoc 中使用“<”和“>”而不进行格式化?

    如果我写
  • 将不同类型的参数传递给 jdbctemplate 查询

    我正在尝试使用带有少量不同类型参数的 where 子句从数据库中检索记录 这是我编写的简单方法 我将breedId和性别作为参数传递 public List
  • Eclipse Java 远程调试器通过 VPN 速度极慢

    我有时被迫离开办公室工作 这意味着我需要通过 VPN 进入我的实验室 我注意到在这种情况下使用 Eclipse 进行远程调试速度非常慢 速度慢到调试器需要 5 7 分钟才能连接到远程 jvm 连接后 每次单步执行断点 行可能需要 20 30
  • 无法捆绑适用于 Mac 的 Java 应用程序 1.8

    我正在尝试将我的 Java 应用程序导出到 Mac 该应用程序基于编译器合规级别 1 7 我尝试了不同的方法来捆绑应用程序 1 日食 我可以用来在 Eclipse 上导出的最新 JVM 版本是 1 6 2 马文 看来Maven上也存在同样的
  • 如何从终端运行处理应用程序

    我目前正在使用加工 http processing org对于一个小项目 但是我不喜欢它附带的文本编辑器 我使用 vim 编写所有代码 我找到了 pde 文件的位置 并且我一直在从 vim 中编辑它们 然后重新打开它们并运行它们 重新加载脚
  • 如何从指定日期获取上周五的日期? [复制]

    这个问题在这里已经有答案了 如何找出上一个 上一个 星期五 或指定日期的任何其他日期的日期 public getDateOnDay Date date String dayName 我不会给出答案 先自己尝试一下 但是 也许这些提示可以帮助
  • 在mockito中使用when进行模拟ContextLoader.getCurrentWebApplicationContext()调用。我该怎么做?

    我试图在使用 mockito 时模拟 ContextLoader getCurrentWebApplicationContext 调用 但它无法模拟 here is my source code Mock org springframewo
  • 如何在桌面浏览器上使用 webdriver 移动网络

    我正在使用 selenium webdriver 进行 AUT 被测应用程序 的功能测试自动化 AUT 是响应式网络 我几乎完成了桌面浏览器的不同测试用例 现在 相同的测试用例也适用于移动浏览器 因为可以从移动浏览器访问 AUT 由于它是响
  • 捕获的图像分辨率太大

    我在做什么 我允许用户捕获图像 将其存储到 SD 卡中并上传到服务器 但捕获图像的分辨率为宽度 4608 像素和高度 2592 像素 现在我想要什么 如何在不影响质量的情况下获得小分辨率图像 例如我可以获取或设置捕获的图像分辨率为原始图像分
  • JGit 检查分支是否已签出

    我正在使用 JGit 开发一个项目 我设法删除了一个分支 但我还想检查该分支是否已签出 我发现了一个变量CheckoutCommand但它是私有的 private boolean isCheckoutIndex return startCo
  • java.lang.IllegalStateException:驱动程序可执行文件的路径必须由 webdriver.chrome.driver 系统属性设置 - Similiar 不回答

    尝试学习 Selenium 我打开了类似的问题 但似乎没有任何帮助 我的代码 package seleniumPractice import org openqa selenium WebDriver import org openqa s

随机推荐

  • linux性能命令详解

    1 查看进程相关信息 1 1 查看当前进程 查看当前进程的启动命令 PID为线程ID 1 ps ef grep 进程信息 获得进程PID 2 cd proc PID 3 ll proc PID 显示的文件夹 cwd符号链接的是进程运行目录
  • feign GET请求不支持对象传参的坑

    问题 GetMapping getByParam String hello Student student throws Exception 如上 feign调用报错500 解决方法 增加 SpringQueryMap GetMapping
  • xxx is not in the sudoers file.This incident will be reported错误

    一 问题解决 在执行sudo命令时会有如下提示 xx is not in the sudoers file This incident will be reported 原因分析 一般这种情况是创建了新用户 没有对应修改sudoers文件或
  • 【文件上传绕过】八、::$DATA上传绕过

    文章目录 一 利用Windows特性 二 源码 三 使用burpsuite抓包在文件后缀加 DATA绕过 一 利用Windows特性 在window的时候如果文件名 DATA 会把 DATA之后的数据当成文件流处理 不会检测后缀名 且保持
  • Myeclipse中Properties文件Unicode码或乱码解决方案

    打开myeclipse的 Window gt Perferences gt General gt Editors gt Context Types 或者 Window gt Perferences gt General gt Context
  • 6. 微积分 - 函数

    Hi 大家好 我是茶桁 经历了前面5节课的基础之后 不知道大家感觉怎么样 我后台接收到了一些反馈 有的同学说比较简单 有的同学说正合适 那有的同学呢 就觉得有些绕 一时之间可能没办法理解和接受 说明小伙伴们的水平呢 还是有一些参差不齐的 那
  • 兔子生兔子的Java解决方式

    最近在学python 其中有这样一道题 古典问题 有一对兔子 从出生后第3个月起每个月都生一对兔子 小兔子长到第三个月后每个月又生一对兔子 假如兔子都不死 问每个月的兔子总数为多少 没有做出来 先用笔在纸上算的时候也是稀里糊涂的 后来想办法
  • python -- opencv获取摄像头时,运行一段时间后突然停止

    问题 在pycharm社区版中 使用opencv获取摄像头时 运行一段时间后 rtsp流突然断开 有概率 断开时报错 websockets exceptions ConnectionClosedError code 1006 connect
  • Spring Boot中解析JSON数据的三种方案

    文章目录 1 JSON简介 2 Spring Boot默认的JSON解析 2 1 使用示例 2 2 修改特定数据的全局JSON格式 2 2 1 自定义MappingJackson2HttpMessageConverter 2 2 2 自定义
  • 假设检验(一):假设检验总体概念

    写在前面的话 最近在学习统计学 这里仅仅是一些学习笔记 方便我自己回顾以及供大家参考 对于统计学我只是初学者 有什么错误之处欢迎大家指出 共同学习 共同进步 一 总体概念 假设检验是一种统计推断方法 其主要用来判断样本与样本 样本与总体之间
  • 使用hiredis实现publish和subscribe

    publish include
  • 提权_Linux提权_suid

    1 MSF连接目标机 生成msf后门 上传到目标机 开启监听 等待运行 gt msfvenom p linux x64 meterpreter reverse tcp LHOST 0 0 0 0 LPORT 6666 i 3 f elf o
  • SylixOS lite Extension工程开发手册

    1 适用范围 本文档介绍了SylixOS Lite版本应用工程的开发流程 适用于使用SylixOS Lite版本开发的相关工程师 2 新建Extension工程 1 选择创建Extension工程 在Project Explorer栏中点击
  • iview表格全选禁止选中设置

    业务需求 表格里面一键全选功能 但是有些数据可能不满足全选的需求 当点击全选时 不满足条件的默认不认其选中 代码如下
  • 微信小程序切片-喝水了关于我们前端制作演示

    微信小程序切片 喝水了关于我们前端制作演示 外部背景的使用 文字识别的使用 复制粘贴设置 边框的设置方法 原始高清播放文件 链接 https pan baidu com s 1nOeOoCj1jfP5rQOg UaQDQ 提取码 32lt
  • Mysql报错 Error querying database. Cause java.sql.SQLSyntaxErrorException

    今天写一个查询功能的时候 出现了一个错误 当我写好后端接口 准备去前端掉用的时候出现了如下错误 Errorqueryingdatabase Cause java sql SQLSyntaxErrorException Youhaveaner
  • leetcode——第55题——跳跃游戏

    题目 给定一个非负整数数组 nums 你最初位于数组的 第一个下标 数组中的每个元素代表你在该位置可以跳跃的最大长度 判断你是否能够到达最后一个下标 class Solution public bool canJump vector
  • XboxOne的kinect在Unity上的开发——开始界面

    好的 欢迎大家来看这个系列的第二部分的内容 这一次呢 我们就直接进入主题 开发切水果游戏本身 这次的切水果的demo呢 我们选择使用ugui来制作 因为ugui相对于NGUI的各种优势 让我们选择了ugui 关于这些呢 大家可以参考我的另一
  • 漏洞扫描是什么?怎么做?

    漏洞扫描 漏洞扫描是指基于漏洞数据库 通过扫描等手段对指定的远程或者本地计算机系统的安全脆弱性进行检测 发现可利用漏洞的一种安全检测 渗透攻击 行为 漏洞扫描按扫描器所处位置 可分为内网扫描和外网扫描 而按照工作方式 又可以将漏洞扫描分为远
  • 【SpringBoot项目实战】图片压缩包上传、解压、存储等等一套流程教学

    SpringBoot项目实战 图片压缩包上传 解压 存储等等一套流程教学 前言 一 压缩包上传 1 接口实现 2 获取压缩包的文件名和文件路径 二 压缩包解压并保存 1 处理压缩包文件方法 解压缩步骤 2 接口中实现处理压缩包 三 总结 前