Java 上传解压zip文件,并且解析文件里面的excel和图片

时间:2023-12-24 13:24:13

需求:上传一个zip文件,zip文件里面包含一个excel和很多图片,需要把excel里面的信息解析出来保存到表中,同时图片也转化成base64保存到数据库表中。

PS:为了方便不同水平的开发人员阅读,我把代码全部写到Controller里面。这个demo的file入参的类型是MultipartFile,很多网上的例子是File类型。这两个类型在解析文件的时候还是有点区别的。

第①个方法:

     /**
* 这个deomo入参的类型是MultipartFile,很多网上的例子是File类型
* @param file (zip)
* @param request
* @param response
* @return
* @throws Exception
*/
@PostMapping("/addPersonsFileOfZip")
public String addPersonsFileOfZip(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception {
String createdId = request.getParameter(KEY_CREATED_ID);
//正常上这里需要检查一下createdId是否为空 //原则上这个uploadZipFilesAndParse方法需要写到service和serviceImpl中
String result =uploadZipFilesAndParse(file,createdId);
return result;
}

第②个方法:

     /**
*返回的是批次号
*同时我另外开了线程处理zip文件里面的图片和excel,
*/
@Override
public String uploadZipFilesAndParse(MultipartFile file, String createdId) throws Exception {
String filename = file.getOriginalFilename();
String fileType = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(Locale.US);
String uuid = UUID.randomUUID().toString();
//判断文件是不是zip类型
if(fileType.equals("zip")){ //FileConfig.localtion是配置文件和config类生产的,我会在评论区附上这些代码,测试demo的时候大家可以直接把FileConfig.localtion替换成D:/test
//String desPath = FileConfig.localtion + File.separator + uuid.replaceAll("-", "");
String desPath = "D:/test" + File.separator + uuid.replaceAll("-", ""); //下面这三行的代码就是把上传文件copy到服务器,一定不要遗漏了。
//遗漏了这个代码,在本地测试环境不会出问题,在服务器上一定会报没有找到文件的错误
String savePath = FileConfig.localtion + File.separator;
File savefile = new File(savePath+filename);
file.transferTo(savefile); FileUtil fileUtil = new FileUtil();
//解压zip文件,我是写在公共类里面,FileUtil类代码评论区见
FileUtil.unZip(file, desPath,savePath);
new Thread(new Runnable() {
@Override
public void run() {
List<File> fileList = new ArrayList<>();
fileList = fileUtil.getSubFiles(desPath,fileList);
for (File oneFile : fileList){
if (oneFile.getName().toLowerCase().endsWith(".xls") || oneFile.getName().toLowerCase().endsWith(".xlsx") ) {
try {
//解析处理excel文件
parseExcelFile(oneFile,createdId,uuid);
} catch (Exception e) {
LogUtils.error(e.getMessage());
}
}else if(oneFile.getName().toLowerCase().endsWith(".jpg")) {
try {
//解析处理图片文件
parseImageFile(oneFile,createdId,uuid);
} catch (Exception e) {
LogUtils.error(e.getMessage());
}
}
} //最后要删除文件,删除文件的方法见评论区FileUtil类
FileUtil.clearFiles(desPath); }
}).start(); }
return uuid;
}

第③个方法:解压zip文件的unzip方法

     public static void unZip(MultipartFile  srcFile, String destDirPath,String savePath) throws RuntimeException, IOException {
long startTime = System.currentTimeMillis(); File file = null;
InputStream ins = srcFile.getInputStream();
file=new File(savePath+srcFile.getOriginalFilename());
LogUtils.info("MultipartFile transform to File,MultipartFile name:"+srcFile.getOriginalFilename());
inputStreamToFile(ins, file); if (!file.exists()) {
throw new RuntimeException(file.getPath() + ",file is not found");
}
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
LogUtils.info("zipFile context name:"+entry.getName());
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator+ entry.getName();
File dir = new File(dirPath);
dir.mkdirs();
}else {
File targetFile = new File(destDirPath + File.separator + entry.getName());
targetFile.setExecutable(true);
if(!targetFile.getParentFile().exists()){
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
InputStream is = zipFile.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
is.close();
}
}
long endTime = System.currentTimeMillis();
LogUtils.info("unZip time-->" + (endTime - startTime) + " ms");
}catch(Exception e) {
throw new RuntimeException("unzip error from FileUtil", e);
} finally {
if(zipFile != null){
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
} //MultipartFile change to file may create a temp file in the project root folder(delete the temp file)
File del = new File(file.toURI());
del.delete();
}
}

第④个方法:unzip方法中的inputStreamToFile方法,这个方法的目的是把MultipartFile转成File类型,但是会在项目根目录下生成一个临时文件,切记要删除

     private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
LogUtils.info("MultipartFile transform to File completed!");
}catch(Exception e) {
e.printStackTrace();
}
}

第⑤个方法:parseExcelFile方法是解析excel的方法,里面包括我自己项目的逻辑处理,大家可以删除这些代码,只保留解析excel的代码就好

     private void parseExcelFile(File file,String createdId,String uuid) throws Exception {

         LogUtils.info("file name:"+file.getName());
FileInputStream is = new FileInputStream(file);
Workbook workbook = WorkbookFactory.create(is);
Sheet sheet = workbook.getSheetAt(0); int firstRowIndex = sheet.getFirstRowNum() + 1;
int lastRowIndex = sheet.getLastRowNum(); List<VapBatchPersonInfo> batchPersonList = new ArrayList<>();
for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { VapBatchPersonInfo vapBatchPersonInfo = new VapBatchPersonInfo();
Row row = sheet.getRow(rIndex);
if (row != null) {
int firstCellIndex = row.getFirstCellNum();
int lastCellIndex = row.getLastCellNum();
JSONObject jsonObject = new JSONObject();
jsonObject.put(KEY_CREATED_ID, createdId); Cell resultCell = row.createCell(lastCellIndex);
Cell msgCell = row.createCell(lastCellIndex + 1);
Boolean flag = false;
for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) {
Cell cell = row.getCell(cIndex);
String titleName = sheet.getRow(0).getCell(cIndex).toString();
String checkTitleName = checkTitleName(cIndex, titleName);
if (!"SUCCESS".equals(checkTitleName)) {
msgCell.setCellValue(checkTitleName);
resultCell.setCellValue("Failed");
flag = true;
break;
}
if (cell != null) {
cell.setCellType(CellType.STRING);
jsonObject.put(titleName, cell.toString());
} }
if (flag) {
rIndex = 0;
lastRowIndex = 0;
} else {
vapBatchPersonInfo.setBatchNo(uuid);
vapBatchPersonInfo.setName(jsonObject.getString("fullName"));
vapBatchPersonInfo.setImageName(jsonObject.getString("imageName"));
vapBatchPersonInfo.setConfidenceThreshold(jsonObject.getString("confidenceThreshold"));
vapBatchPersonInfo.setCreatedId(jsonObject.getString("createdId"));
vapBatchPersonInfo.setIdentityNo(jsonObject.getString("identityNo"));
vapBatchPersonInfo.setCreatedDate(new Date());
vapBatchPersonInfo.setLastUpdatedId(jsonObject.getString("createdId"));
vapBatchPersonInfo.setLastUpdatedDate(new Date());
vapBatchPersonInfo.setStatus(TaskStatus.RUNNING);
batchPersonList.add(vapBatchPersonInfo);
}
}
}
batchPersonInfoRepository.saveAll(batchPersonList); }

第⑥个方法:parseImageFile方法是解析图片的方法

     private void parseImageFile(File file, String createdId, String uuid) throws Exception {

         String imgStr ="";
FileInputStream fis = new FileInputStream(file);
byte[] buffer = new byte[(int) file.length()];
int offset = 0;
int numRead = 0;
while (offset < buffer.length && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) {
offset += numRead;
}
if (offset != buffer.length) {
throw new IOException("Could not completely read file " + file.getName());
}
fis.close();
Base64 encoder = new Base64();
imgStr = Base64.encodeBase64String(buffer);
imgStr.length();
LogUtils.info("file name:"+file.getName());
// LogUtils.info("file imgStr:"+imgStr);
// LogUtils.info("file imgStr.length:"+imgStr.length()); }

最后附上FileConfig和FileUtil的代码

FileConfig代码:

import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component; /**
*Jun 12, 2019
*
* FileConfig.java
*/
@ConfigurationProperties(prefix = "upload")
@Component
@Order
public class FileConfig { public static String localtion;
public static String maxFileSize;
public static String maxRequestSize; /**
* @param localtion the localtion to set
*/
public void setLocaltion(String localtion) {
FileConfig.localtion = localtion;
} /**
* @param maxFileSize the maxFileSize to set
*/
public void setMaxFileSize(String maxFileSize) {
FileConfig.maxFileSize = maxFileSize;
} /**
* @param maxRequestSize the maxRequestSize to set
*/
public void setMaxRequestSize(String maxRequestSize) {
FileConfig.maxRequestSize = maxRequestSize;
} }

FileConfig类里面读取的配置文件信息:

配置文件类型是yml,大家也可以自己改成properties文件格式

upload:
#localtion: ${UPLOAD_DIR:/home/data/test}
localtion: ${UPLOAD_DIR:D:/test}
maxFileSize: 10240KB
maxRequestSize: 102400KB

FileUtil类的代码:

 import java.io.*;
import java.nio.channels.FileChannel;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.attribute.PosixFilePermission;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import org.springframework.web.multipart.MultipartFile; import sg.com.mha.ummi.common.util.LogUtils; public class FileUtil { public static void clearFiles(String workspaceRootPath) {
File file = new File(workspaceRootPath);
deleteFile(file);
} public static void deleteFile(File file) {
if (file.exists()) {
if (file.isDirectory()) {
File[] files = file.listFiles();
for (int i = 0; i < files.length; i++) {
deleteFile(files[i]);
}
}
}
file.delete();
} public static void fileWrite(String str, String fileNamePath) throws IOException {
FileWriter writer = null;
try {
File file = new File(fileNamePath);
if (!file.getParentFile().exists()) {
file.getParentFile().mkdirs();
file.createNewFile();
}
writer = new FileWriter(file, true);
writer.write(str + System.getProperty("line.separator")); } catch (IOException e) {
LogUtils.error(e.getMessage());
} finally {
if (writer != null) {
writer.close();
}
}
} public static void changePermission(File dirFile, int mode) throws IOException {
char[] modes = Integer.toOctalString(mode).toCharArray();
if (modes.length != 3) {
return;
}
Set<PosixFilePermission> perms = new HashSet<PosixFilePermission>();
switch (modes[0]) {
case '1':
perms.add(PosixFilePermission.OWNER_EXECUTE);
break;
case '2':
perms.add(PosixFilePermission.OWNER_WRITE);
break;
case '4':
perms.add(PosixFilePermission.OWNER_READ);
break;
case '5':
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_EXECUTE);
break;
case '6':
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
break;
case '7':
perms.add(PosixFilePermission.OWNER_READ);
perms.add(PosixFilePermission.OWNER_WRITE);
perms.add(PosixFilePermission.OWNER_EXECUTE);
break; default:
break;
}
switch (modes[1]) {
case '1':
perms.add(PosixFilePermission.GROUP_EXECUTE);
break;
case '2':
perms.add(PosixFilePermission.GROUP_WRITE);
break;
case '4':
perms.add(PosixFilePermission.GROUP_READ);
break;
case '5':
perms.add(PosixFilePermission.GROUP_READ);
perms.add(PosixFilePermission.GROUP_EXECUTE);
break;
case '6':
perms.add(PosixFilePermission.GROUP_READ);
perms.add(PosixFilePermission.GROUP_WRITE);
break;
case '7':
perms.add(PosixFilePermission.GROUP_READ);
perms.add(PosixFilePermission.GROUP_WRITE);
perms.add(PosixFilePermission.GROUP_EXECUTE);
break;
default:
break;
}
switch (modes[2]) {
case '1':
perms.add(PosixFilePermission.OTHERS_EXECUTE);
break;
case '2':
perms.add(PosixFilePermission.OTHERS_WRITE);
break;
case '4':
perms.add(PosixFilePermission.OTHERS_READ);
break;
case '5':
perms.add(PosixFilePermission.OTHERS_EXECUTE);
perms.add(PosixFilePermission.OTHERS_READ);
break;
case '6':
perms.add(PosixFilePermission.OTHERS_READ);
perms.add(PosixFilePermission.OTHERS_WRITE);
break;
case '7':
perms.add(PosixFilePermission.OTHERS_EXECUTE);
perms.add(PosixFilePermission.OTHERS_READ);
perms.add(PosixFilePermission.OTHERS_WRITE);
break;
default:
break;
} try {
Path path = Paths.get(dirFile.getAbsolutePath());
Files.setPosixFilePermissions(path, perms);
} catch (Exception e) {
e.printStackTrace();
}
} public static File mkFile(String fileName) {
File f = new File(fileName);
try {
if (f.exists()) {
f.delete();
}
f.createNewFile();
} catch (IOException e) {
e.printStackTrace();
}
return f;
} public static void copyDirAndFile(String oldPath, String newPath) throws IOException {
if (!(new File(newPath)).exists()) {
(new File(newPath)).mkdir();
}
File file = new File(oldPath);
//file name list
String[] filePaths = file.list();
for (String filePath : filePaths) {
String oldFullPath = oldPath + file.separator + filePath;
String newFullPath = newPath + file.separator + filePath;
File oldFile = new File(oldFullPath);
File newFile = new File(newFullPath);
if (oldFile.isDirectory()) {
copyDirAndFile(oldFullPath, newFullPath);
} else if (oldFile.isFile()) {
copyFile(oldFile, newFile);
}
}
} public static void copyFile(File source, File dest) throws IOException {
FileChannel inputChannel = null;
FileChannel outputChannel = null;
try {
inputChannel = new FileInputStream(source).getChannel();
outputChannel = new FileOutputStream(dest).getChannel();
outputChannel.transferFrom(inputChannel, 0, inputChannel.size());
} finally {
inputChannel.close();
outputChannel.close();
}
} /**
* @author panchaoyuan
* @param srcFile Unzipped file
* @param destDirPath Unzipped destination folder
* @throws RuntimeException
* @throws IOException
*/
public static void unZip(MultipartFile srcFile, String destDirPath,String savePath) throws RuntimeException, IOException {
long startTime = System.currentTimeMillis(); File file = null;
InputStream ins = srcFile.getInputStream();
file=new File(savePath+srcFile.getOriginalFilename());
LogUtils.info("MultipartFile transform to File,MultipartFile name:"+srcFile.getOriginalFilename());
inputStreamToFile(ins, file); if (!file.exists()) {
throw new RuntimeException(file.getPath() + ",file is not found");
}
ZipFile zipFile = null;
try {
zipFile = new ZipFile(file);
Enumeration<?> entries = zipFile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
LogUtils.info("zipFile context name:"+entry.getName());
if (entry.isDirectory()) {
String dirPath = destDirPath + File.separator+ entry.getName();
File dir = new File(dirPath);
dir.mkdirs();
}else {
File targetFile = new File(destDirPath + File.separator + entry.getName());
targetFile.setExecutable(true);
if(!targetFile.getParentFile().exists()){
targetFile.getParentFile().mkdirs();
}
targetFile.createNewFile();
InputStream is = zipFile.getInputStream(entry);
FileOutputStream fos = new FileOutputStream(targetFile);
int len;
byte[] buf = new byte[1024];
while ((len = is.read(buf)) != -1) {
fos.write(buf, 0, len);
}
fos.close();
is.close();
}
}
long endTime = System.currentTimeMillis();
LogUtils.info("unZip time-->" + (endTime - startTime) + " ms");
}catch(Exception e) {
throw new RuntimeException("unzip error from FileUtil", e);
} finally {
if(zipFile != null){
try {
zipFile.close();
} catch (IOException e) {
e.printStackTrace();
}
} //MultipartFile change to file may create a temp file in the project root folder(delete the temp file)
File del = new File(file.toURI());
del.delete();
}
} /**
* MultipartFile changed to File
* @author panchaoyuan
* @return
*/
private static void inputStreamToFile(InputStream ins, File file) {
try {
OutputStream os = new FileOutputStream(file);
int bytesRead = 0;
byte[] buffer = new byte[8192];
while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) {
os.write(buffer, 0, bytesRead);
}
os.close();
ins.close();
LogUtils.info("MultipartFile transform to File completed!");
}catch(Exception e) {
e.printStackTrace();
}
} /**
* @author panchaoyuan
*/
public List<File> getSubFiles(String desFile,List<File> fileList) {
File file = new File(desFile);
File[] files = file.listFiles();
for (File fileIndex : files) {
if (!fileIndex.exists()) {
throw new NullPointerException("Cannot find " + fileIndex);
} else if (fileIndex.isFile()) {
fileList.add(fileIndex);
} else {
if (fileIndex.isDirectory()) {
getSubFiles(fileIndex.getAbsolutePath(),fileList);
}
}
}
return fileList;
} }

水平有限,可能写得不是很完整,大家copy这些代码的时候有可能因为引入包的不同,不一定走得成功,如有疑问,在评论区联系本人,写得不好的地方也欢迎指正。