根据资源路径加载ZIP压缩包中指定的资源

本文介绍如何使用Java的ZipFile和ZipEntry类从JAR、WAR或EAR文件中根据资源路径加载文件流。提供了具体的方法实现,并解释了资源路径的构成方式。

JAR、WAR、EAR、在文件结构上,三者并没有什么不同,它们都采用ZIP或JAR档案文件压缩格式。针对ZIP压缩文档中的类文件或者配置文件,如何根据该资源路径就能直接加载到其文件流呢? java.util.zip包中的ZipFile类和ZipEntry类两者结合即可根据资源的路径加载到其对应的文件流。

    /**

     *GetInputStreambyzip entry name from specifiedjarfile.

     */

    public InputStream getInputStreamFromEntry(String jarFile, String entryName) {

       ZipFile zf = new ZipFile(jarFile);

       ZipEntry ze = zf.getEntry(entryName);

       return zf.getInputStream(ze);

    }

注意,用来确定每个资源的名字是压缩文档中资源的实际路径名,而不是包(package)中类的名字。也就是说,java.util.zip包中的ZipEntry类的名字应为“java/util/zip/ZipEntry”,而不是"java.util.zip.ZipEntry"。事实上,Class类中的getResourceAsStream方法中即将类的全限定名中“.”全部替换成“/”构成资源的路径。

    /**

     *Addapackagename prefixif the nameis notabsoluteRemoveleading"/"

     *ifnameis absolute

     */

    private StringresolveName(String name) {

        if (name ==null) {

            return name;

        }

        if (!name.startsWith("/")) {

            Class c = this;

            while (c.isArray()) {

                c = c.getComponentType();

            }

            String baseName = c.getName();

            int index = baseName.lastIndexOf('.');

            if (index != -1) {

                name = baseName.substring(0, index).replace('.','/')

                    +"/"+name;

            }

        } else {

            name = name.substring(1);

        }

        return name;

    }

 

方法含义很简单

  • 对于不是以“/”开头的参数,就认为这个路径是相对于当前类的路径,所以加载当前包中的资源只要写资源文件的名字就可以了。方法最大的一块代码就是为了得到当前类的路径,然后和传进来的相对路径参数拼起来,作为资源文件的绝对路径丢给CL。
  • 对于以“/”开头的参数,就认为参数是资源文件的绝对路径,将这个斜线去掉之后,丢给CL去加载就行了。

<think>好的,我需要解决用户的问题:在Spring Boot中解压macOS系统上的压缩包并进行文件过滤。首先,我需要明确用户的具体需求。macOS常用的压缩格式包括ZIP、TAR.GZ等,用户可能需要对解压后的文件进行过滤,比如只处理特定类型或符合某些名称规则的文件。 接下来,我得考虑Spring Boot中的实现方式。Java本身有处理ZIP和GZIP的库,但可能需要第三方库来处理更多格式,比如Apache Commons Compress。此外,文件过滤需要在解压过程中检查每个文件的名称或属性,决定是否保留。 然后,我需要分步骤设计解决方案。首先选择合适的压缩库,比如使用java.util.zip处理ZIP,Apache Commons Compress处理TAR.GZ。然后,在解压时遍历压缩包中的条目,对每个条目应用过滤条件,符合条件的才解压到目标目录。 同时,需要注意macOS压缩包可能包含隐藏文件(如._开头的资源派生文件),用户可能希望过滤掉这些文件。因此,在过滤逻辑中需要加入对文件名的判断,排除这些不需要的文件。 还需要考虑路径安全问题,防止解压时路径穿越漏洞,确保解压后的文件不会覆盖或写入到非目标目录的位置。可以使用Java的Path API来规范化路径,确保解压路径在目标目录内。 另外,可能需要处理不同编码的文件名,尤其是macOS可能使用UTF-8编码,而Java在处理ZIP时默认使用平台编码,可能导致乱码。因此,需要指定正确的编码方式,或者使用第三方库如Zip4j来处理编码问题。 最后,编写示例代码,展示如何实现这些步骤,并添加相关的依赖项说明,比如在pom.xml中添加Apache Commons Compress的依赖。同时,提醒用户注意异常处理和资源释放,避免内存泄漏或文件锁问题。 总结步骤:选择压缩库、遍历压缩条目、应用过滤规则、安全解压文件、处理编码问题,并提供代码示例和依赖配置。</think>在Spring Boot中实现解压macOS系统压缩包并过滤文件的功能,需结合Java压缩库和文件过滤逻辑。以下是具体实现步骤: --- ### 1. 添加依赖 使用Apache Commons Compress处理多种压缩格式,需在`pom.xml`中添加: ```xml <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-compress</artifactId> <version>1.21</version> </dependency> ``` --- ### 2. 实现解压与过滤 #### **ZIP格式解压(含过滤)** ```java public void unzipWithFilter(Path zipFile, Path outputDir, Predicate<String> filter) throws IOException { try (ZipFile zip = new ZipFile(zipFile.toFile())) { Enumeration<ZipArchiveEntry> entries = zip.getEntries(); while (entries.hasMoreElements()) { ZipArchiveEntry entry = entries.nextElement(); if (!filter.test(entry.getName())) continue; // 过滤文件 Path targetPath = outputDir.resolve(entry.getName()).normalize(); if (!targetPath.startsWith(outputDir)) { throw new IOException("路径穿越风险: " + entry.getName()); } if (entry.isDirectory()) { Files.createDirectories(targetPath); } else { Files.copy(zip.getInputStream(entry), targetPath); } } } } ``` #### **TAR.GZ格式解压(含过滤)** ```java public void untarGzWithFilter(Path tarGzFile, Path outputDir, Predicate<String> filter) throws IOException { try (TarArchiveInputStream tarInput = new TarArchiveInputStream( new GzipCompressorInputStream(Files.newInputStream(tarGzFile)))) { TarArchiveEntry entry; while ((entry = tarInput.getNextTarEntry()) != null) { if (!filter.test(entry.getName())) continue; // 过滤文件 Path targetPath = outputDir.resolve(entry.getName()).normalize(); if (!targetPath.startsWith(outputDir)) { throw new IOException("路径穿越风险: " + entry.getName()); } if (entry.isDirectory()) { Files.createDirectories(targetPath); } else { Files.copy(tarInput, targetPath); } } } } ``` --- ### 3. 过滤规则示例 过滤macOS隐藏文件及指定扩展名: ```java Predicate<String> macFilter = entryName -> !entryName.startsWith("__MACOSX/") && // 过滤系统目录 !entryName.contains("/._") && // 过滤资源派生文件 entryName.endsWith(".txt"); // 仅保留txt文件 ``` --- ### 4. 调用示例 ```java @RestController public class UnzipController { @PostMapping("/unzip") public String handleUnzip(@RequestParam String sourcePath) { Path zipPath = Paths.get(sourcePath); Path outputDir = Paths.get("/target/directory"); try { if (sourcePath.endsWith(".zip")) { unzipWithFilter(zipPath, outputDir, macFilter); } else if (sourcePath.endsWith(".tar.gz")) { untarGzWithFilter(zipPath, outputDir, macFilter); } return "解压成功"; } catch (IOException e) { return "解压失败: " + e.getMessage(); } } } ``` --- ### 关键注意事项 1. **路径安全**:使用`normalize()`和`startsWith(outputDir)`防止路径穿越攻击[^3] 2. **编码问题**:若文件名含中文,需指定编码(如ZipFile使用`Charset.forName("UTF-8")`) 3. **性能优化**:大文件解压时建议分块读取,避免内存溢出 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值