找回密码
立即注册
搜索
热搜: Java Python Linux Go
发回帖 发新帖

1906

积分

0

好友

252

主题
发表于 14 小时前 | 查看: 2| 回复: 0

一张惊讶的简笔画表情

在处理批量图片上传的场景时,通过压缩包一次性上传是个高效的选择。过去我常用zip4j来处理压缩包,后来发现国产的Hutool工具包里也有封装好的ZipUtil,它是对java.util.zip的封装,功能足够且能减少一个外部依赖,于是便切换了过来。

本文将通过一个实际案例,演示如何使用SpringBoot结合Hutool,实现一个接收图片压缩包、自动解压、校验文件并与数据库联动的完整接口。这个案例的背景是管理用户的人脸照片。

一、构建文件上传接口

首先,我们需要创建一个用于接收压缩包的POST接口。

1. 接口定义与参数接收

在控制器类上使用@RestController注解,并通过@PostMapping定义接口路径。接口接收类型为multipart/form-data的表单数据,使用@RequestParam获取名为“zipFile”的文件参数。

@RestController
public class Controller {

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

这个接口的默认访问地址是:http://127.0.0.1:8080/upload

2. 配置文件路径与初始化

我们需要从配置文件中读取文件存储的根路径。使用@Value注解注入配置值,同时别忘记添加@Component注解以确保能正确扫描到配置。

//组件扫描注解,用于获取配置文件内容
@Component
@RestController
public class Controller {

    //获取配置文件中的文件上传物理路径,例:C:/upload/
    @Value("${config.uploadPath}")
    private String uploadPath;

    /**
     * 压缩包文件上传
     *
     * @param zipFile 压缩包文件
     * @return R 返回实体类
     */
    @PostMapping("/upload")
    public R upload(@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. 核心解压与校验方法

这个方法负责三步操作:保存上传的压缩包、解压到指定目录、校验解压出的文件。

/**
 * 处理压缩包文件
 *
 * @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. 在接口中整合业务逻辑

现在,在upload接口中调用上面的方法,并加入具体的业务逻辑。本案例中,我们假设图片文件名前缀对应数据库中的用户ID。

//组件扫描注解,用于获取配置文件内容
@Component
@RestController
public class Controller {

    //获取配置文件中的文件上传物理路径,例:C:/upload/
    @Value("${config.uploadPath}")
    private String uploadPath;

    //Service层
    @Resource
    private Service service;

    /**
     * 压缩包文件上传
     *
     * @param zipFile 压缩包文件
     * @return R 返回实体类
     */
    @PostMapping("/upload")
    public R upload(@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,在Java应用中进行匹配和后续存储。在实际开发中,你可以在遍历文件的步骤里加入更复杂的逻辑,比如文件类型深度校验、图像内容分析、分发到不同存储服务等。

回顾整个流程,从接收MultipartFile,到使用Hutool的ZipUtil.unzip()解压,再到结合业务操作数据库,形成了一个清晰的处理闭环。我发现在寻找解决方案时,网上资料往往比较零散,因此自己实践时尽量记录得完整些,既方便自己回顾,也希望能帮到遇到类似问题的朋友。如果你有更好的思路或工具推荐,欢迎在云栈社区交流讨论。




上一篇:POMDP维修决策:数据不全下数控机床多状态评估与成本优化
下一篇:OpenClaw:4个月GitHub星破25万,AI代理如何“算力屠杀”传统软件?
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-3-4 19:58 , Processed in 0.395562 second(s), 43 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表