Java解析zip文件,并识别压缩包里面的文件转换成可操作的IO流

前几天项目遇到一个棘手的问题,批量上传人员的证件照,因为java操作文件夹不好操作,最后决定把存放人员证件照的文件夹压缩成zip文件,通过java去解析,然后把里面的文件转成list集合,这里使用的jdk提供的 java.util.zip包

第一步:引入需要的maven依赖

<dependency>
     <groupId>commons-fileupload</groupId>
     <artifactId>commons-fileupload</artifactId>
     <version>1.3.3</version>
</dependency>

第二步:创建UnzipFileVo对象(文件的载体)

@Data
public class UnzipFileVo {

   
    private MultipartFile file;

}

第三步:编写转换工具类

public class ZipUtil {

    public static List<UnzipFileVo> Ectract(MultipartFile multipartFile) throws IOException {
        List<UnzipFileVo> list= new ArrayList<>();
        //获取文件输入流
        InputStream input = multipartFile.getInputStream();
        //获取ZIP输入流(一定要指定字符集Charset.forName("GBK")否则会报java.lang.IllegalArgumentException: MALFORMED)
        ZipInputStream zipInputStream = new ZipInputStream(new BufferedInputStream(input), Charset.forName("GBK"));
        ZipFile zf = toFile(multipartFile);
        //定义ZipEntry置为null,避免由于重复调用zipInputStream.getNextEntry造成的不必要的问题
        ZipEntry ze = null;
        //循环遍历
        while ((ze =zipInputStream.getNextEntry())!= null) {
            InputStream is = zf.getInputStream(ze);

            UnzipFileVo unzipFileVo = new UnzipFileVo();
            unzipFileVo.setFile(getMultipartFile(is,ze.getName()));
            list.add(unzipFileVo);
        }
        //一定记得关闭流
        zipInputStream.closeEntry();
        input.close();
        return list;
    }

    /**
     * 获取封装得MultipartFile
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return MultipartFile
     */
    public static MultipartFile getMultipartFile(InputStream inputStream, String fileName) {
        FileItem fileItem = createFileItem(inputStream, fileName);
        //CommonsMultipartFile是feign对multipartFile的封装,但是要FileItem类对象
        return new CommonsMultipartFile(fileItem);
    }

    private  static  ZipFile toFile(MultipartFile multipartFile) throws IOException {
        if (multipartFile == null || multipartFile.getSize() <= 0) {
            return null;
        }
        File file = multipartFileToFile(multipartFile);
        if (file == null || !file.exists()) {
            return null;
        }
        ZipFile zipFile = new ZipFile(file, Charset.forName("GBK"));
        return zipFile;
    }

    private static File multipartFileToFile(MultipartFile multipartFile) {
        File file = null;
        InputStream inputStream = null;
        OutputStream outputStream = null;
        try {
            inputStream = multipartFile.getInputStream();
            file = new File(multipartFile.getOriginalFilename());
            outputStream = new FileOutputStream(file);
            write(inputStream, outputStream);
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return file;
    }

    public static void  write(InputStream inputStream, OutputStream outputStream) {
        byte[] buffer = new byte[4096];
        try {
            int count = inputStream.read(buffer, 0, buffer.length);
            while (count != -1) {
                outputStream.write(buffer, 0, count);
                count = inputStream.read(buffer, 0, buffer.length);
            }
        } catch (RuntimeException e) {
            throw e;
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage(), e);
        }
    }

    /**
     * FileItem类对象创建
     *
     * @param inputStream inputStream
     * @param fileName    fileName
     * @return FileItem
     */
    public static FileItem createFileItem(InputStream inputStream, String fileName) {
        FileItemFactory factory = new DiskFileItemFactory(16, null);
        String textFieldName = "file";
        FileItem item = factory.createItem(textFieldName, MediaType.MULTIPART_FORM_DATA_VALUE, true, fileName);
        int bytesRead = 0;
        byte[] buffer = new byte[8192];
        OutputStream os = null;
        //使用输出流输出输入流的字节
        try {
            os = item.getOutputStream();
            while ((bytesRead = inputStream.read(buffer, 0, 8192)) != -1) {
                os.write(buffer, 0, bytesRead);
            }
            inputStream.close();
        } catch (IOException e) {

            throw new IllegalArgumentException("文件上传失败");
        } finally {
            if (os != null) {
                try {
                    os.close();
                } catch (IOException e) {

                }
            }
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                }
            }
        }

        return item;
    }
}

第四步:调用工具

   @PostMapping("/UploadManagerPhoto")
    public ActionResult uploadManagerPhoto(MultipartFile file) throws IOException {
        if(Objects.isNull(file) || file.isEmpty()) {//验证文件是否为空
            return ActionResult.fail("上传文件为空或不存在");
        }
        List<UnzipFileVo> unzipFileVoList = UnZipUtil.Ectract(file);
        List<UnzipFileVo> collect = unzipFileVoList.stream().filter(item -> item.getFile().getOriginalFilename().contains(".") && item.getFile().getSize() > 0).collect(Collectors.toList());//获取zip文件里面的文件,并组装到新的List对象//过滤文件夹
        //上面就是把zip压缩包的内容转换称了文件流集合,下面可根据自己的业务对文件进行操作
        int sum = 0;
        for (int i = 0; i < collect.size(); i++) {
            //这是我自己封装的上传方法,大家可以根据自己的实际情况对文件进行操作
            UploaderVO uploaderVO = fileService.uploader("document", collect.get(i).getFile());//调取上传方法,返回上传成功对象
            sum++;
        }
        return ActionResult.success("解析zip成功,成功上传"+sum+"条数据");
    }

不懂的可以私信

  • 9
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值