功能概述
readShpZip方法根据ZIP文件路径,将其解压到指定的上传目录,并返回解压后的目录路径。
执行步骤
| 步骤 | 说明 |
|---|
| 1 | 校验参数,检查文件是否存在 |
| 2 | 提取文件名(去除.zip后缀)作为解压目录名 |
| 3 | 调用extractZip解压文件 |
| 4 | 验证解压结果,返回解压目录路径 |
核心代码
readShpZip 方法
publicstaticStringreadShpZip(StringfilePath,StringuploadPath)throwsIOException{StringdirPath="";// 参数校验if(filePath==null||uploadPath==null){thrownewIllegalArgumentException("文件路径和上传路径不能为空");}Filefile=newFile(filePath);if(file.exists()){try{// 获取文件名,去除.zip后缀StringoriginalFilename=file.getName();if(!originalFilename.toLowerCase().endsWith(".zip")){thrownewCommonException("文件名无效或不是 ZIP 文件");}StringfileName=originalFilename.substring(0,originalFilename.length()-4);dirPath=uploadPath+File.separator+fileName;// 解压try(InputStreaminputStream=newFileInputStream(file)){FileTools.extractZip(inputStream,dirPath);}// 验证解压结果FiledecompressionDir=newFile(dirPath);if(!decompressionDir.exists()||!decompressionDir.isDirectory()){thrownewCommonException("解压失败:目标目录未生成");}}catch(Exceptione){e.printStackTrace();}}else{thrownewCommonException("旧文件不存在或损坏,请重新上传");}returndirPath;}
extractZip 解压核心方法
publicstaticvoidextractZip(InputStreamzipInputStream,StringdestDirPath)throwsIOException{PathdestDir=Paths.get(destDirPath);Files.createDirectories(destDir);// 写入临时文件PathtempZip=Files.createTempFile("extract_",".zip");try{Files.copy(zipInputStream,tempZip,StandardCopyOption.REPLACE_EXISTING);if(Files.size(tempZip)==0)thrownewIOException("ZIP 文件为空");// 暴力扫描模式解压intcount=forceExtractBySignature(tempZip,destDir);if(count>0){System.out.println("解压完成,共 "+count+" 个文件");return;}thrownewIOException("无法解压此文件");}finally{Files.deleteIfExists(tempZip);}}// 暴力扫描模式:逐字节查找PK签名解压privatestaticintforceExtractBySignature(PathzipFile,PathdestDir)throwsIOException{byte[]data=Files.readAllBytes(zipFile);intpos=0,count=0;while(pos<data.length-4){if(data[pos]=='P'&&data[pos+1]=='K'&&data[pos+2]==3&&data[pos+3]==4){try(InputStreamslice=newByteArrayInputStream(data,pos,data.length-pos);ZipArchiveInputStreamzis=newZipArchiveInputStream(slice,"GBK",true,true)){ZipArchiveEntryentry=zis.getNextZipEntry();if(entry!=null&&!entry.isDirectory()){Stringname=entry.getName();Pathpath=destDir.resolve(name).normalize();if(path.startsWith(destDir)){// 防路径穿越Files.createDirectories(path.getParent());try(OutputStreamos=Files.newOutputStream(path)){IOUtils.copy(zis,os);count++;}}}}catch(Exceptionignored){}}pos++;}returncount;}
执行流程
文件路径 + 上传目录 ↓ 参数校验 ──→ 抛出异常 ↓ 文件存在? ──→ 抛出异常 ↓ 提取文件名(去.zip) → 构建解压目录路径 ↓ extractZip解压 ──→ 暴力扫描PK签名 ↓ 验证目录是否生成 ──→ 抛出异常 ↓ 返回解压目录路径
入参说明
| 参数名 | 类型 | 必填 | 说明 |
|---|
filePath | String | ✅ | ZIP压缩包的完整路径 |
uploadPath | String | ✅ | 解压目标目录路径 |
返回值
调用示例
StringzipFilePath="/upload/temp/shp_data.zip";StringuploadDir="/upload/shp";StringdecompressionPath=FileTools.readShpZip(zipFilePath,uploadDir);// 返回: /upload/shp/shp_data