[经验] 获取压缩包文件名列表
前言
最近开发一个校园系统,需要从三方导入学生数据,但是没有学生头像,需手动上传学生压缩包,将图片存储至服务器内部,配置静态资源访问路径,供网站使用,记录一下使用过程。
环境
- spring boot 2.3.5.RELEASE
- java 8
- hutool 5.0.4
- zip4j 1.3.2
思路
递归文件路径获取文件名及文件路径
1、将文件保存至本地
2、解压文件
3、递归文件目录,采集文件名
代码逻辑
UnzipUtil 工具类
import cn.hutool.core.util.StrUtil;
import lombok.extern.slf4j.Slf4j;
import net.lingala.zip4j.core.ZipFile;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.util.Map;
import java.util.Objects;
/**
* 解压rar/zip工具类
*/
@SuppressWarnings("AlibabaUndefineMagicConstant")
@Slf4j
public class UnzipUtil {
public static final String ZIP_EXT = "zip";
/**
* zip文件解压
*
* @param destPath 解压文件路径
* @param zipFile 压缩文件
*/
public static boolean unzip(File zipFile, String destPath) {
return unzip(zipFile, null, destPath);
}
/**
* zip文件解压
*
* @param destPath 解压文件路径
* @param zipFile 压缩文件
* @param password 解压密码(如果有)
*/
public static boolean unzip(File zipFile, String password, String destPath) {
boolean i = false;
try {
ZipFile zip = new ZipFile(zipFile);
/*zip4j默认用GBK编码去解压,这里设置编码为GBK的*/
zip.setFileNameCharset("GBK");
log.info("begin unpack zip file....");
zip.extractAll(destPath);
// 如果解压需要密码
if (zip.isEncrypted()) {
zip.setPassword(password);
}
i = true;
} catch (Exception e) {
log.error("unPack zip file to " + destPath + " fail ....", e.getMessage(), e);
}
return i;
}
/**
* 获取文件名与文件路径的关联
*
* @param path 目标路径
* @param rootPath 压缩包相对路径路径
* @param namePathMap 关联
*/
public static void namePathMap(String path, String rootPath, Map<String, String> namePathMap) {
File file = new File(path);
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < Objects.requireNonNull(files).length; i++) {
if (files[i].isDirectory()) {
namePathMap(files[i].getPath(),rootPath, namePathMap);
} else {
String path1 = files[i].getPath();
if (FilenameUtils.isExtension(path1, ZIP_EXT)) {
return;
}
String fileName = path1.substring(path1.lastIndexOf("\\") + 1, path1.lastIndexOf("."));
String imgPath = files[i].getAbsolutePath();
if (StrUtil.isNotBlank(rootPath)) {
imgPath = File.separator + imgPath.substring(imgPath.indexOf(rootPath));
}
namePathMap.put(fileName, imgPath);
}
}
} else {
String path1 = file.getPath();
if (FilenameUtils.isExtension(path1, ZIP_EXT)) {
return;
}
String fileName = path1.substring(path1.lastIndexOf("\\") + 1, path1.lastIndexOf("."));
String imgPath = file.getAbsolutePath();
if (StrUtil.isNotBlank(rootPath)) {
imgPath = File.separator + imgPath.substring(imgPath.indexOf(rootPath));
}
namePathMap.put(fileName, imgPath);
}
}
}
逻辑代码
/**
* 获取文件名及路径对应
*
* @param zipFile zip文件
* @param destPath 目标路径
* @return id及文件名对应关系
* @throws Exception 异常
*/
protected Map<String, String> zipFileNames(MultipartFile zipFile, String destPath) throws Exception {
if (Objects.isNull(zipFile) || !FilenameUtils.isExtension(zipFile.getOriginalFilename(), UnzipUtil.ZIP_EXT)) {
throw new JcBootException("请上传照片压缩文件");
}
try {
Path path = Paths.get(destPath);
Files.createDirectories(path);
} catch (IOException e) {
log.error("Failed to create unzipped directory - {}", destPath, e);
throw new JcBootException(StrFormatter.format("Failed to create unzipped directory - {}", destPath));
}
File tempZip = new File(destPath + zipFile.getOriginalFilename());
try {
zipFile.transferTo(tempZip);
} catch (IOException | IllegalStateException e) {
log.error("Failed to save the zip file locally - {}", tempZip, e);
throw new JcBootException(StrFormatter.format("Failed to save the zip file locally - {}", tempZip));
}
boolean unzip = UnzipUtil.unzip(tempZip, destPath);
if (!unzip) {
log.error("Failed to unzip the file - {}", tempZip);
throw new JcBootException(StrFormatter.format("Failed to unzip the file - {}", tempZip));
}
boolean del = FileUtil.del(tempZip);
log.info("{} to delete source zip file!", del ? "Success" : "Failed");
Map<String, String> namePath = new HashMap<>();
UnzipUtil.namePathMap(destPath,FilenameUtils.getBaseName(zipFile.getOriginalFilename()), namePath);
return namePath;
}
验证
为了简化上传逻辑,使用了本地File转MultipartFile,直接调用
/**
* 将file转为 MultipartFile
* @param file 文件
* @return MultipartFile
*/
public static MultipartFile getMultipartFile(File file) {
FileItem item = new DiskFileItemFactory().createItem("file"
, MediaType.MULTIPART_FORM_DATA_VALUE
, true
, file.getName());
try (InputStream input = new FileInputStream(file);
OutputStream os = item.getOutputStream()) {
// 流转移
IOUtils.copy(input, os);
} catch (Exception e) {
throw new IllegalArgumentException("Invalid file: " + e, e);
}
return new CommonsMultipartFile(item);
}
运行
public static void main(String[] args) throws Exception {
File file = new File("D:\\pic\\pic.zip");
MultipartFile multipartFile = getMultipartFile(file);
Map<String, String> fileNames = zipFileNames(multipartFile, "D:\\pic\\");
log.info(JSONUtil.toJsonPrettyStr(fileNames));
}
结果
{
"霍建华": "\\pic\\霍建华.jpg",
"林心如": "\\pic\\林心如.jpg",
"杨幂": "\\pic\\杨幂.jpg",
"胡歌": "\\pic\\胡歌.jpg"
}
总结
本篇文章主要是记录了压缩包上传并获取压缩包文件名称的操作思路,如大家有更好的方案及方法欢迎讨论留言,谢谢。