需求:上传一个zip文件,zip文件里面包含一个excel和很多图片,需要把excel里面的信息解析出来保存到表中,同时图片也转化成base64保存到数据库表中。
PS:为了方便不同水平的开发人员阅读,我把代码全部写到Controller里面。这个demo的file入参的类型是MultipartFile,很多网上的例子是File类型。这两个类型在解析文件的时候还是有点区别的。
第①个方法:
1 /** 2 * 这个deomo入参的类型是MultipartFile,很多网上的例子是File类型 3 * @param file (zip) 4 * @param request 5 * @param response 6 * @return 7 * @throws Exception 8 */ 9 @PostMapping("/addPersonsFileOfZip") 10 public String addPersonsFileOfZip(@RequestParam("file") MultipartFile file, HttpServletRequest request) throws Exception { 11 String createdId = request.getParameter(KEY_CREATED_ID); 12 //正常上这里需要检查一下createdId是否为空 13 14 //原则上这个uploadZipFilesAndParse方法需要写到service和serviceImpl中 15 String result =uploadZipFilesAndParse(file,createdId); 16 return result; 17 }
第②个方法:
1 /** 2 *返回的是批次号 3 *同时我另外开了线程处理zip文件里面的图片和excel, 4 */ 5 @Override 6 public String uploadZipFilesAndParse(MultipartFile file, String createdId) throws Exception { 7 String filename = file.getOriginalFilename(); 8 String fileType = filename.substring(filename.lastIndexOf(".") + 1).toLowerCase(Locale.US); 9 String uuid = UUID.randomUUID().toString(); 10 //判断文件是不是zip类型 11 if(fileType.equals("zip")){ 12 13 //FileConfig.localtion是配置文件和config类生产的,我会在评论区附上这些代码,测试demo的时候大家可以直接把FileConfig.localtion替换成D:/test 14 //String desPath = FileConfig.localtion + File.separator + uuid.replaceAll("-", ""); 15 String desPath = "D:/test" + File.separator + uuid.replaceAll("-", ""); 16 17 18 //下面这三行的代码就是把上传文件copy到服务器,一定不要遗漏了。 19 //遗漏了这个代码,在本地测试环境不会出问题,在服务器上一定会报没有找到文件的错误 20 String savePath = FileConfig.localtion + File.separator; 21 File savefile = new File(savePath+filename); 22 file.transferTo(savefile); 23 24 FileUtil fileUtil = new FileUtil(); 25 //解压zip文件,我是写在公共类里面,FileUtil类代码评论区见 26 FileUtil.unZip(file, desPath,savePath); 27 new Thread(new Runnable() { 28 @Override 29 public void run() { 30 ListfileList = new ArrayList<>(); 31 fileList = fileUtil.getSubFiles(desPath,fileList); 32 for (File oneFile : fileList){ 33 if (oneFile.getName().toLowerCase().endsWith(".xls") || oneFile.getName().toLowerCase().endsWith(".xlsx") ) { 34 try { 35 //解析处理excel文件 36 parseExcelFile(oneFile,createdId,uuid); 37 } catch (Exception e) { 38 LogUtils.error(e.getMessage()); 39 } 40 }else if(oneFile.getName().toLowerCase().endsWith(".jpg")) { 41 try { 42 //解析处理图片文件 43 parseImageFile(oneFile,createdId,uuid); 44 } catch (Exception e) { 45 LogUtils.error(e.getMessage()); 46 } 47 } 48 } 49 50 //最后要删除文件,删除文件的方法见评论区FileUtil类 51 FileUtil.clearFiles(desPath); 52 53 } 54 }).start(); 55 56 } 57 return uuid; 58 }
第③个方法:解压zip文件的unzip方法
1 public static void unZip(MultipartFile srcFile, String destDirPath,String savePath) throws RuntimeException, IOException { 2 long startTime = System.currentTimeMillis(); 3 4 File file = null; 5 InputStream ins = srcFile.getInputStream(); 6 file=new File(savePath+srcFile.getOriginalFilename()); 7 LogUtils.info("MultipartFile transform to File,MultipartFile name:"+srcFile.getOriginalFilename()); 8 inputStreamToFile(ins, file); 9 10 if (!file.exists()) { 11 throw new RuntimeException(file.getPath() + ",file is not found"); 12 } 13 ZipFile zipFile = null; 14 try { 15 zipFile = new ZipFile(file); 16 Enumeration> entries = zipFile.entries(); 17 while (entries.hasMoreElements()) { 18 ZipEntry entry = (ZipEntry) entries.nextElement(); 19 LogUtils.info("zipFile context name:"+entry.getName()); 20 if (entry.isDirectory()) { 21 String dirPath = destDirPath + File.separator+ entry.getName(); 22 File dir = new File(dirPath); 23 dir.mkdirs(); 24 }else { 25 File targetFile = new File(destDirPath + File.separator + entry.getName()); 26 targetFile.setExecutable(true); 27 if(!targetFile.getParentFile().exists()){ 28 targetFile.getParentFile().mkdirs(); 29 } 30 targetFile.createNewFile(); 31 InputStream is = zipFile.getInputStream(entry); 32 FileOutputStream fos = new FileOutputStream(targetFile); 33 int len; 34 byte[] buf = new byte[1024]; 35 while ((len = is.read(buf)) != -1) { 36 fos.write(buf, 0, len); 37 } 38 fos.close(); 39 is.close(); 40 } 41 } 42 long endTime = System.currentTimeMillis(); 43 LogUtils.info("unZip time-->" + (endTime - startTime) + " ms"); 44 }catch(Exception e) { 45 throw new RuntimeException("unzip error from FileUtil", e); 46 } finally { 47 if(zipFile != null){ 48 try { 49 zipFile.close(); 50 } catch (IOException e) { 51 e.printStackTrace(); 52 } 53 } 54 55 //MultipartFile change to file may create a temp file in the project root folder(delete the temp file) 56 File del = new File(file.toURI()); 57 del.delete(); 58 } 59 }
第④个方法:unzip方法中的inputStreamToFile方法,这个方法的目的是把MultipartFile转成File类型,但是会在项目根目录下生成一个临时文件,切记要删除
1 private static void inputStreamToFile(InputStream ins, File file) { 2 try { 3 OutputStream os = new FileOutputStream(file); 4 int bytesRead = 0; 5 byte[] buffer = new byte[8192]; 6 while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { 7 os.write(buffer, 0, bytesRead); 8 } 9 os.close(); 10 ins.close(); 11 LogUtils.info("MultipartFile transform to File completed!"); 12 }catch(Exception e) { 13 e.printStackTrace(); 14 } 15 }
第⑤个方法:parseExcelFile方法是解析excel的方法,里面包括我自己项目的逻辑处理,大家可以删除这些代码,只保留解析excel的代码就好
1 private void parseExcelFile(File file,String createdId,String uuid) throws Exception { 2 3 LogUtils.info("file name:"+file.getName()); 4 FileInputStream is = new FileInputStream(file); 5 Workbook workbook = WorkbookFactory.create(is); 6 Sheet sheet = workbook.getSheetAt(0); 7 8 int firstRowIndex = sheet.getFirstRowNum() + 1; 9 int lastRowIndex = sheet.getLastRowNum(); 10 11 ListbatchPersonList = new ArrayList<>(); 12 for (int rIndex = firstRowIndex; rIndex <= lastRowIndex; rIndex++) { 13 14 VapBatchPersonInfo vapBatchPersonInfo = new VapBatchPersonInfo(); 15 Row row = sheet.getRow(rIndex); 16 if (row != null) { 17 int firstCellIndex = row.getFirstCellNum(); 18 int lastCellIndex = row.getLastCellNum(); 19 JSONObject jsonObject = new JSONObject(); 20 jsonObject.put(KEY_CREATED_ID, createdId); 21 22 Cell resultCell = row.createCell(lastCellIndex); 23 Cell msgCell = row.createCell(lastCellIndex + 1); 24 Boolean flag = false; 25 for (int cIndex = firstCellIndex; cIndex < lastCellIndex; cIndex++) { 26 Cell cell = row.getCell(cIndex); 27 String titleName = sheet.getRow(0).getCell(cIndex).toString(); 28 String checkTitleName = checkTitleName(cIndex, titleName); 29 if (!"SUCCESS".equals(checkTitleName)) { 30 msgCell.setCellValue(checkTitleName); 31 resultCell.setCellValue("Failed"); 32 flag = true; 33 break; 34 } 35 if (cell != null) { 36 cell.setCellType(CellType.STRING); 37 jsonObject.put(titleName, cell.toString()); 38 } 39 40 } 41 if (flag) { 42 rIndex = 0; 43 lastRowIndex = 0; 44 } else { 45 vapBatchPersonInfo.setBatchNo(uuid); 46 vapBatchPersonInfo.setName(jsonObject.getString("fullName")); 47 vapBatchPersonInfo.setImageName(jsonObject.getString("imageName")); 48 vapBatchPersonInfo.setConfidenceThreshold(jsonObject.getString("confidenceThreshold")); 49 vapBatchPersonInfo.setCreatedId(jsonObject.getString("createdId")); 50 vapBatchPersonInfo.setIdentityNo(jsonObject.getString("identityNo")); 51 vapBatchPersonInfo.setCreatedDate(new Date()); 52 vapBatchPersonInfo.setLastUpdatedId(jsonObject.getString("createdId")); 53 vapBatchPersonInfo.setLastUpdatedDate(new Date()); 54 vapBatchPersonInfo.setStatus(TaskStatus.RUNNING); 55 batchPersonList.add(vapBatchPersonInfo); 56 } 57 } 58 } 59 batchPersonInfoRepository.saveAll(batchPersonList); 60 61 }
第⑥个方法:parseImageFile方法是解析图片的方法
1 private void parseImageFile(File file, String createdId, String uuid) throws Exception { 2 3 String imgStr =""; 4 FileInputStream fis = new FileInputStream(file); 5 byte[] buffer = new byte[(int) file.length()]; 6 int offset = 0; 7 int numRead = 0; 8 while (offset < buffer.length && (numRead = fis.read(buffer, offset, buffer.length - offset)) >= 0) { 9 offset += numRead; 10 } 11 if (offset != buffer.length) { 12 throw new IOException("Could not completely read file " + file.getName()); 13 } 14 fis.close(); 15 Base64 encoder = new Base64(); 16 imgStr = Base64.encodeBase64String(buffer); 17 imgStr.length(); 18 LogUtils.info("file name:"+file.getName()); 19 // LogUtils.info("file imgStr:"+imgStr); 20 // LogUtils.info("file imgStr.length:"+imgStr.length()); 21 22 }
最后附上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类的代码:
1 import java.io.*; 2 import java.nio.channels.FileChannel; 3 import java.nio.file.Files; 4 import java.nio.file.Path; 5 import java.nio.file.Paths; 6 import java.nio.file.attribute.PosixFilePermission; 7 import java.util.ArrayList; 8 import java.util.Enumeration; 9 import java.util.HashSet; 10 import java.util.List; 11 import java.util.Set; 12 import java.util.zip.ZipEntry; 13 import java.util.zip.ZipFile; 14 15 import org.springframework.web.multipart.MultipartFile; 16 17 import sg.com.mha.ummi.common.util.LogUtils; 18 19 20 public class FileUtil { 21 22 public static void clearFiles(String workspaceRootPath) { 23 File file = new File(workspaceRootPath); 24 deleteFile(file); 25 } 26 27 public static void deleteFile(File file) { 28 if (file.exists()) { 29 if (file.isDirectory()) { 30 File[] files = file.listFiles(); 31 for (int i = 0; i < files.length; i++) { 32 deleteFile(files[i]); 33 } 34 } 35 } 36 file.delete(); 37 } 38 39 public static void fileWrite(String str, String fileNamePath) throws IOException { 40 FileWriter writer = null; 41 try { 42 File file = new File(fileNamePath); 43 if (!file.getParentFile().exists()) { 44 file.getParentFile().mkdirs(); 45 file.createNewFile(); 46 } 47 writer = new FileWriter(file, true); 48 writer.write(str + System.getProperty("line.separator")); 49 50 } catch (IOException e) { 51 LogUtils.error(e.getMessage()); 52 } finally { 53 if (writer != null) { 54 writer.close(); 55 } 56 } 57 } 58 59 public static void changePermission(File dirFile, int mode) throws IOException { 60 char[] modes = Integer.toOctalString(mode).toCharArray(); 61 if (modes.length != 3) { 62 return; 63 } 64 Setperms = new HashSet (); 65 switch (modes[0]) { 66 case '1': 67 perms.add(PosixFilePermission.OWNER_EXECUTE); 68 break; 69 case '2': 70 perms.add(PosixFilePermission.OWNER_WRITE); 71 break; 72 case '4': 73 perms.add(PosixFilePermission.OWNER_READ); 74 break; 75 case '5': 76 perms.add(PosixFilePermission.OWNER_READ); 77 perms.add(PosixFilePermission.OWNER_EXECUTE); 78 break; 79 case '6': 80 perms.add(PosixFilePermission.OWNER_READ); 81 perms.add(PosixFilePermission.OWNER_WRITE); 82 break; 83 case '7': 84 perms.add(PosixFilePermission.OWNER_READ); 85 perms.add(PosixFilePermission.OWNER_WRITE); 86 perms.add(PosixFilePermission.OWNER_EXECUTE); 87 break; 88 89 default: 90 break; 91 } 92 switch (modes[1]) { 93 case '1': 94 perms.add(PosixFilePermission.GROUP_EXECUTE); 95 break; 96 case '2': 97 perms.add(PosixFilePermission.GROUP_WRITE); 98 break; 99 case '4': 100 perms.add(PosixFilePermission.GROUP_READ); 101 break; 102 case '5': 103 perms.add(PosixFilePermission.GROUP_READ); 104 perms.add(PosixFilePermission.GROUP_EXECUTE); 105 break; 106 case '6': 107 perms.add(PosixFilePermission.GROUP_READ); 108 perms.add(PosixFilePermission.GROUP_WRITE); 109 break; 110 case '7': 111 perms.add(PosixFilePermission.GROUP_READ); 112 perms.add(PosixFilePermission.GROUP_WRITE); 113 perms.add(PosixFilePermission.GROUP_EXECUTE); 114 break; 115 default: 116 break; 117 } 118 switch (modes[2]) { 119 case '1': 120 perms.add(PosixFilePermission.OTHERS_EXECUTE); 121 break; 122 case '2': 123 perms.add(PosixFilePermission.OTHERS_WRITE); 124 break; 125 case '4': 126 perms.add(PosixFilePermission.OTHERS_READ); 127 break; 128 case '5': 129 perms.add(PosixFilePermission.OTHERS_EXECUTE); 130 perms.add(PosixFilePermission.OTHERS_READ); 131 break; 132 case '6': 133 perms.add(PosixFilePermission.OTHERS_READ); 134 perms.add(PosixFilePermission.OTHERS_WRITE); 135 break; 136 case '7': 137 perms.add(PosixFilePermission.OTHERS_EXECUTE); 138 perms.add(PosixFilePermission.OTHERS_READ); 139 perms.add(PosixFilePermission.OTHERS_WRITE); 140 break; 141 default: 142 break; 143 } 144 145 try { 146 Path path = Paths.get(dirFile.getAbsolutePath()); 147 Files.setPosixFilePermissions(path, perms); 148 } catch (Exception e) { 149 e.printStackTrace(); 150 } 151 } 152 153 public static File mkFile(String fileName) { 154 File f = new File(fileName); 155 try { 156 if (f.exists()) { 157 f.delete(); 158 } 159 f.createNewFile(); 160 } catch (IOException e) { 161 e.printStackTrace(); 162 } 163 return f; 164 } 165 166 167 public static void copyDirAndFile(String oldPath, String newPath) throws IOException { 168 if (!(new File(newPath)).exists()) { 169 (new File(newPath)).mkdir(); 170 } 171 File file = new File(oldPath); 172 //file name list 173 String[] filePaths = file.list(); 174 for (String filePath : filePaths) { 175 String oldFullPath = oldPath + file.separator + filePath; 176 String newFullPath = newPath + file.separator + filePath; 177 File oldFile = new File(oldFullPath); 178 File newFile = new File(newFullPath); 179 if (oldFile.isDirectory()) { 180 copyDirAndFile(oldFullPath, newFullPath); 181 } else if (oldFile.isFile()) { 182 copyFile(oldFile, newFile); 183 } 184 } 185 } 186 187 public static void copyFile(File source, File dest) throws IOException { 188 FileChannel inputChannel = null; 189 FileChannel outputChannel = null; 190 try { 191 inputChannel = new FileInputStream(source).getChannel(); 192 outputChannel = new FileOutputStream(dest).getChannel(); 193 outputChannel.transferFrom(inputChannel, 0, inputChannel.size()); 194 } finally { 195 inputChannel.close(); 196 outputChannel.close(); 197 } 198 } 199 200 /** 201 * @author panchaoyuan 202 * @param srcFile Unzipped file 203 * @param destDirPath Unzipped destination folder 204 * @throws RuntimeException 205 * @throws IOException 206 */ 207 public static void unZip(MultipartFile srcFile, String destDirPath,String savePath) throws RuntimeException, IOException { 208 long startTime = System.currentTimeMillis(); 209 210 File file = null; 211 InputStream ins = srcFile.getInputStream(); 212 file=new File(savePath+srcFile.getOriginalFilename()); 213 LogUtils.info("MultipartFile transform to File,MultipartFile name:"+srcFile.getOriginalFilename()); 214 inputStreamToFile(ins, file); 215 216 if (!file.exists()) { 217 throw new RuntimeException(file.getPath() + ",file is not found"); 218 } 219 ZipFile zipFile = null; 220 try { 221 zipFile = new ZipFile(file); 222 Enumeration> entries = zipFile.entries(); 223 while (entries.hasMoreElements()) { 224 ZipEntry entry = (ZipEntry) entries.nextElement(); 225 LogUtils.info("zipFile context name:"+entry.getName()); 226 if (entry.isDirectory()) { 227 String dirPath = destDirPath + File.separator+ entry.getName(); 228 File dir = new File(dirPath); 229 dir.mkdirs(); 230 }else { 231 File targetFile = new File(destDirPath + File.separator + entry.getName()); 232 targetFile.setExecutable(true); 233 if(!targetFile.getParentFile().exists()){ 234 targetFile.getParentFile().mkdirs(); 235 } 236 targetFile.createNewFile(); 237 InputStream is = zipFile.getInputStream(entry); 238 FileOutputStream fos = new FileOutputStream(targetFile); 239 int len; 240 byte[] buf = new byte[1024]; 241 while ((len = is.read(buf)) != -1) { 242 fos.write(buf, 0, len); 243 } 244 fos.close(); 245 is.close(); 246 } 247 } 248 long endTime = System.currentTimeMillis(); 249 LogUtils.info("unZip time-->" + (endTime - startTime) + " ms"); 250 }catch(Exception e) { 251 throw new RuntimeException("unzip error from FileUtil", e); 252 } finally { 253 if(zipFile != null){ 254 try { 255 zipFile.close(); 256 } catch (IOException e) { 257 e.printStackTrace(); 258 } 259 } 260 261 //MultipartFile change to file may create a temp file in the project root folder(delete the temp file) 262 File del = new File(file.toURI()); 263 del.delete(); 264 } 265 } 266 267 /** 268 * MultipartFile changed to File 269 * @author panchaoyuan 270 * @return 271 */ 272 private static void inputStreamToFile(InputStream ins, File file) { 273 try { 274 OutputStream os = new FileOutputStream(file); 275 int bytesRead = 0; 276 byte[] buffer = new byte[8192]; 277 while ((bytesRead = ins.read(buffer, 0, 8192)) != -1) { 278 os.write(buffer, 0, bytesRead); 279 } 280 os.close(); 281 ins.close(); 282 LogUtils.info("MultipartFile transform to File completed!"); 283 }catch(Exception e) { 284 e.printStackTrace(); 285 } 286 } 287 288 /** 289 * @author panchaoyuan 290 */ 291 public List getSubFiles(String desFile,List fileList) { 292 File file = new File(desFile); 293 File[] files = file.listFiles(); 294 for (File fileIndex : files) { 295 if (!fileIndex.exists()) { 296 throw new NullPointerException("Cannot find " + fileIndex); 297 } else if (fileIndex.isFile()) { 298 fileList.add(fileIndex); 299 } else { 300 if (fileIndex.isDirectory()) { 301 getSubFiles(fileIndex.getAbsolutePath(),fileList); 302 } 303 } 304 } 305 return fileList; 306 } 307 308 309 }
水平有限,可能写得不是很完整,大家copy这些代码的时候有可能因为引入包的不同,不一定走得成功,如有疑问,在评论区联系本人,写得不好的地方也欢迎指正。