OssFileService.java 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686
  1. package edu.nju.service;
  2. import com.aliyun.oss.ClientBuilderConfiguration;
  3. import com.aliyun.oss.ClientException;
  4. import com.aliyun.oss.OSSException;
  5. import com.aliyun.oss.model.*;
  6. import edu.nju.configuration.OSSConfiguration;
  7. import edu.nju.entities.BugDetail;
  8. import edu.nju.model.enums.UploadType;
  9. import lombok.extern.slf4j.Slf4j;
  10. import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
  11. import org.springframework.web.multipart.MultipartFile;
  12. import java.util.List;
  13. import com.alibaba.fastjson.JSON;
  14. import com.aliyun.oss.OSS;
  15. import edu.nju.dao.*;
  16. import edu.nju.entities.*;
  17. import edu.nju.util.OssAliyun;
  18. import edu.nju.util.TransUtil;
  19. import org.json.JSONArray;
  20. import org.springframework.beans.factory.annotation.Autowired;
  21. import org.springframework.beans.factory.annotation.Value;
  22. import org.springframework.stereotype.Service;
  23. import java.io.*;
  24. import java.lang.reflect.Field;
  25. import java.nio.charset.StandardCharsets;
  26. import java.util.*;
  27. import java.util.concurrent.ExecutorService;
  28. import java.util.concurrent.Executors;
  29. import java.util.concurrent.TimeUnit;
  30. import java.util.zip.ZipEntry;
  31. import java.util.zip.ZipFile;
  32. import java.util.zip.ZipOutputStream;
  33. /**
  34. * @Author JiaWei Xu
  35. * @Date 2021-01-04 15:53
  36. * @Email xjwhhh233@outlook.com
  37. */
  38. @Slf4j
  39. @Service
  40. @ConditionalOnExpression("${useOss}==true")
  41. public class OssFileService implements FileService {
  42. private static final int BUFFER_SIZE = 2048;
  43. @Autowired
  44. ExamDao examDao;
  45. @Autowired
  46. BugDao bugDao;
  47. @Autowired
  48. ReportDao reportDao;
  49. @Autowired
  50. TestCaseDao testCaseDao;
  51. @Autowired
  52. CaseToBugDao caseToBugDao;
  53. @Autowired
  54. BugScoreDao bugScoreDao;
  55. @Autowired
  56. BugMirrorDao bugMirrorDao;
  57. @Autowired
  58. BugHistoryDao bugHistoryDao;
  59. @Autowired
  60. BugDetailDao bugDetailDao;
  61. @Autowired
  62. private OSSConfiguration ossConfig;
  63. private OSS client;
  64. private String key;
  65. @Value("${upload.thread.maxSize}")
  66. private String uploadThreadMaxSize;
  67. @Value("${upload.chunkSize}")
  68. private String uploadChunkSize;
  69. @Value("${upload.chunkMaxPartCount}")
  70. private String uploadChunkMaxPartCount;
  71. private ExecutorService executorService;
  72. private List<PartETag> partETags = Collections.synchronizedList(new ArrayList<PartETag>());
  73. @Value("${cpSerialNum}")
  74. private String cpSerialNum;
  75. @Value("${save.path}")
  76. private String savePath;
  77. @Value("${save.folder}")
  78. private String folderName;
  79. @Value("${save.input}")
  80. private String inputName;
  81. @Value("${save.output}")
  82. private String outputName;
  83. @Override
  84. public void uploadImage() {
  85. }
  86. @Override
  87. public List<BugDetail> importBugInfo(MultipartFile sourceZipFile, MultipartFile sourceJsonFile, String originalCaseId, String cpSerialNum) {
  88. return saveBugDetail(sourceZipFile,sourceJsonFile,originalCaseId,cpSerialNum);
  89. }
  90. @Override
  91. public List<BugDetail> exportBugInfo(String caseId) {
  92. List<BugDetail> bugDetailList = getBugDetailListByCaseId(caseId);
  93. bugDetailToFile(bugDetailList,caseId);
  94. return bugDetailList;
  95. }
  96. @Override
  97. public String sliceUploadFile(String fileName, String caseId, MultipartFile file){
  98. key = fileName;
  99. executorService = Executors.newFixedThreadPool(Integer.parseInt(uploadThreadMaxSize));
  100. ClientBuilderConfiguration conf = new ClientBuilderConfiguration();
  101. // 连接空闲超时时间,超时则关闭连接(单位:毫秒)。默认为60000毫秒。
  102. conf.setIdleConnectionTime(Long.parseLong(ossConfig.getIdleConnectionTime()));
  103. client = ossConfig.ossClientConf(conf);
  104. try {
  105. // 获取文件后缀并新建一个类型为File的targetFile,用于后续MultipartFile转File
  106. String prefix=fileName.substring(fileName.lastIndexOf("."));
  107. final File targetFile = File.createTempFile(fileName, prefix);
  108. // 声明一个上传ID,uploadId
  109. String uploadId = claimUploadId();
  110. log.info("声明一个上传ID:" + uploadId);
  111. // 分片上传的每片的大小
  112. final long partSize = Integer.parseInt(uploadChunkSize) * 1024 * 1024L; // 5MB
  113. // MultipartFile转成File
  114. file.transferTo(targetFile);
  115. long fileLength = targetFile.length();
  116. // 计算分片的数量
  117. int partCount = (int) (fileLength / partSize);
  118. if (fileLength % partSize != 0) {
  119. partCount++;
  120. }
  121. // 校验是否超过限制的最大分片数量
  122. if (partCount > Integer.parseInt(uploadChunkMaxPartCount)) {
  123. throw new RuntimeException("分片数量不能超过" + uploadChunkMaxPartCount);
  124. } else {
  125. log.info("分片数量为: " + partCount);
  126. }
  127. // 分片上传文件到OSS
  128. log.info("------------开始分片上传文件到OSS------------");
  129. // 重新初始化,否则会一直add导致数量不一致
  130. partETags = Collections.synchronizedList(new ArrayList<PartETag>());
  131. for (int i = 0; i < partCount; i++) {
  132. long startPos = i * partSize;
  133. long curPartSize = (i + 1 == partCount) ? (fileLength - startPos) : partSize;
  134. executorService.execute(new PartUploader(targetFile, startPos, curPartSize, i + 1, uploadId));
  135. }
  136. // 等待所有分片上传完成
  137. executorService.shutdown();
  138. while (!executorService.isTerminated()) {
  139. try {
  140. executorService.awaitTermination(1, TimeUnit.SECONDS);
  141. } catch (InterruptedException e) {
  142. e.printStackTrace();
  143. }
  144. }
  145. log.info("partETags的数量:" + partETags.size());
  146. // 判断是否所有的分片上传完成
  147. if (partETags.size() != partCount) {
  148. throw new RuntimeException("文件上传失败,由于存在部分分片未上传完成。");
  149. } else {
  150. log.info("----------文件分片上传成功 " + fileName + "----------");
  151. }
  152. // View all parts uploaded recently
  153. // listAllParts(uploadId);
  154. // Complete to upload multiparts
  155. completeMultipartUpload(uploadId);
  156. // Fetch the object that newly created at the step below.
  157. // log.info("Fetching an object");
  158. // client.getObject(new GetObjectRequest(ossConfig.getBucketName(), key), targetFile);
  159. return ossConfig.getBaseUrl() + "/" + key;
  160. } catch (OSSException oe) {
  161. log.info("Caught an OSSException, which means your request made it to OSS, "
  162. + "but was rejected with an error response for some reason.");
  163. log.info("Error Message: " + oe.getErrorMessage());
  164. log.info("Error Code: " + oe.getErrorCode());
  165. log.info("Request ID: " + oe.getRequestId());
  166. log.info("Host ID: " + oe.getHostId());
  167. } catch (ClientException ce) {
  168. log.info("Caught an ClientException, which means the client encountered "
  169. + "a serious internal problem while trying to communicate with OSS, "
  170. + "such as not being able to access the network.");
  171. log.info("Error Message: " + ce.getMessage());
  172. } catch (IOException e) {
  173. e.printStackTrace();
  174. } finally {
  175. /*
  176. * Do not forget to shut down the client finally to release all allocated resources.
  177. */
  178. if (client != null) {
  179. client.shutdown();
  180. }
  181. }
  182. return "";
  183. }
  184. private class PartUploader implements Runnable {
  185. private File localFile;
  186. private long startPos;
  187. private long partSize;
  188. private int partNumber;
  189. private String uploadId;
  190. public PartUploader(File localFile, long startPos, long partSize, int partNumber, String uploadId) {
  191. this.localFile = localFile;
  192. this.startPos = startPos;
  193. this.partSize = partSize;
  194. this.partNumber = partNumber;
  195. this.uploadId = uploadId;
  196. }
  197. @Override
  198. public void run() {
  199. InputStream instream = null;
  200. try {
  201. instream = new FileInputStream(this.localFile);
  202. instream.skip(this.startPos);
  203. UploadPartRequest uploadPartRequest = new UploadPartRequest();
  204. uploadPartRequest.setBucketName(ossConfig.getBucketName());
  205. uploadPartRequest.setKey(key);
  206. uploadPartRequest.setUploadId(this.uploadId);
  207. uploadPartRequest.setInputStream(instream);
  208. uploadPartRequest.setPartSize(this.partSize);
  209. uploadPartRequest.setPartNumber(this.partNumber);
  210. UploadPartResult uploadPartResult = client.uploadPart(uploadPartRequest);
  211. log.info("分片 " + this.partNumber + " 完成");
  212. synchronized (partETags) {
  213. partETags.add(uploadPartResult.getPartETag());
  214. }
  215. } catch (Exception e) {
  216. e.printStackTrace();
  217. } finally {
  218. if (instream != null) {
  219. try {
  220. instream.close();
  221. } catch (IOException e) {
  222. e.printStackTrace();
  223. }
  224. }
  225. }
  226. }
  227. }
  228. private String claimUploadId() {
  229. InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(ossConfig.getBucketName(), key);
  230. InitiateMultipartUploadResult result = client.initiateMultipartUpload(request);
  231. return result.getUploadId();
  232. }
  233. private void completeMultipartUpload(String uploadId) {
  234. // Make part numbers in ascending order
  235. Collections.sort(partETags, new Comparator<PartETag>() {
  236. @Override
  237. public int compare(PartETag p1, PartETag p2) {
  238. return p1.getPartNumber() - p2.getPartNumber();
  239. }
  240. });
  241. log.info("Completing to upload multiparts");
  242. CompleteMultipartUploadRequest completeMultipartUploadRequest =
  243. new CompleteMultipartUploadRequest(ossConfig.getBucketName(), key, uploadId, partETags);
  244. client.completeMultipartUpload(completeMultipartUploadRequest);
  245. }
  246. /**
  247. * 根据caseId获取对应bug信息
  248. *
  249. * @param caseId
  250. * @return
  251. */
  252. public List<BugDetail> getBugDetailListByCaseId(String caseId) {
  253. List<BugDetail> bugDetailList = new ArrayList<>();
  254. Exam crowdCase = examDao.findById(caseId);
  255. if (crowdCase != null) {
  256. List<Report> reportList = reportDao.findByCaseId(caseId);
  257. for (Report report : reportList) {
  258. String reportId = report.getId();
  259. List<TestCase> testCaseList = testCaseDao.findByReport(reportId);
  260. for (TestCase testCase : testCaseList) {
  261. String testCaseId = testCase.getId();
  262. CaseToBug caseToBug = caseToBugDao.findById(testCaseId);
  263. if (caseToBug != null) {
  264. List<String> bugIdList = caseToBug.getBug_id();
  265. for (String bugId : bugIdList) {
  266. BugDetail bugDetail = new BugDetail();
  267. bugDetail.setId(bugId);
  268. //bug基本属性
  269. Bug bug = bugDao.findByid(bugId);
  270. if (bug != null) {
  271. bugDetail.setBugCategory(bug.getBug_category());
  272. bugDetail.setSeverity(TransUtil.severityTransFromInt(bug.getSeverity()));
  273. bugDetail.setRecurrent(TransUtil.recurrentTransFromInt(bug.getRecurrent()));
  274. bugDetail.setBugCreateTime(TransUtil.formatTimeMillis(bug.getCreate_time_millis()));
  275. bugDetail.setBugPage(bug.getBug_page());
  276. bugDetail.setTitle(bug.getTitle());
  277. bugDetail.setBugDescription(bug.getDescription());
  278. bugDetail.setImgUrl(bug.getImg_url());
  279. }
  280. //bugScore属性
  281. BugScore bugScore = bugScoreDao.findById(bugId);
  282. if (bugScore != null) {
  283. bugDetail.setScore(bugScore.getGrade());
  284. }
  285. //bugMirror属性
  286. BugMirror bugMirror = bugMirrorDao.findById(bugId);
  287. if (bugMirror != null) {
  288. Set<String> goodWorkerIdSet = new HashSet<>();
  289. Set<String> badWorkerIdSet = new HashSet<>();
  290. Set<String> goodReportIdSet = bugMirror.getGood();
  291. Set<String> badReportIdSet = bugMirror.getBad();
  292. int goodNum = 0;
  293. int badNum = 0;
  294. for (String goodReportId : goodReportIdSet) {
  295. Report goodReport = reportDao.findById(goodReportId);
  296. if (goodReport != null) {
  297. goodNum++;
  298. goodWorkerIdSet.add(goodReport.getWorker_id());
  299. }
  300. }
  301. for (String badReportId : badReportIdSet) {
  302. Report badReport = reportDao.findById(badReportId);
  303. if (badReport != null) {
  304. badNum++;
  305. badWorkerIdSet.add(badReport.getWorker_id());
  306. }
  307. }
  308. bugDetail.setGoodNum(goodNum);
  309. bugDetail.setBadNum(badNum);
  310. bugDetail.setGoodWorkerId(goodWorkerIdSet);
  311. bugDetail.setBadWorkerId(badWorkerIdSet);
  312. }
  313. //bugHistory属性
  314. BugHistory bugHistory = bugHistoryDao.findByid(bugId);
  315. if (bugHistory != null) {
  316. bugDetail.setParent(bugHistory.getParent());
  317. bugDetail.setChildren(bugHistory.getChildren());
  318. bugDetail.setRoot(bugHistory.getRoot());
  319. }
  320. //testCase属性
  321. bugDetail.setTestCaseId(testCase.getId());
  322. bugDetail.setTestCaseName(testCase.getName());
  323. bugDetail.setTestCaseFront(testCase.getFront());
  324. bugDetail.setTestCaseBehind(testCase.getBehind());
  325. bugDetail.setTestCaseDescription(testCase.getDescription());
  326. bugDetail.setTestCaseCreateTime(TransUtil.formatTimeMillis(testCase.getCreate_time_millis()));
  327. //report属性
  328. bugDetail.setReportId(report.getId());
  329. bugDetail.setReportName(report.getName());
  330. bugDetail.setScriptLocation(report.getScript_location());
  331. bugDetail.setReportLocation(report.getReport_location());
  332. bugDetail.setLogLocation(report.getLog_location());
  333. bugDetail.setDeviceModel(report.getDevice_model());
  334. bugDetail.setDeviceBrand(report.getDevice_brand());
  335. bugDetail.setDeviceOs(report.getDevice_os());
  336. //worker属性
  337. bugDetail.setWorkerId(report.getWorker_id());
  338. //众测任务属性
  339. bugDetail.setCaseAppName(crowdCase.getName());
  340. bugDetail.setCasePaperType(crowdCase.getPaper_type());
  341. bugDetail.setCaseTestType(crowdCase.getTest_type());
  342. bugDetail.setCaseDescription(crowdCase.getDescription());
  343. bugDetail.setCaseRequireDoc("");
  344. bugDetail.setCaseTakeId(report.getCase_take_id());
  345. //cp序列号
  346. bugDetail.setCpSerialNum(cpSerialNum);
  347. bugDetailList.add(bugDetail);
  348. }
  349. }
  350. }
  351. }
  352. }
  353. return bugDetailList;
  354. }
  355. public List<BugDetail> saveBugDetail(MultipartFile sourceZipFile, MultipartFile sourceJsonFile, String originalCaseId, String cpSerialNum) {
  356. try {
  357. //读取文件流并保存在本地
  358. String zipFilePath= savePath + folderName + inputName + "/imageZip/"+originalCaseId+"/"+cpSerialNum+"/"+originalCaseId+".zip";
  359. File zipFile=new File(zipFilePath);
  360. if(!zipFile.getParentFile().exists()) { zipFile.getParentFile().mkdirs(); }
  361. if(!sourceZipFile.isEmpty()) { sourceZipFile.transferTo(zipFile); }
  362. String jsonFilePath= savePath + folderName + inputName + "/"+originalCaseId+"/"+cpSerialNum+"/"+originalCaseId+".json";
  363. File jsonFile=new File(jsonFilePath);
  364. if(!jsonFile.getParentFile().exists()) { jsonFile.getParentFile().mkdirs(); }
  365. if(!sourceJsonFile.isEmpty()) { sourceJsonFile.transferTo(jsonFile); }
  366. //读取本地文件
  367. BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(jsonFile));
  368. ByteArrayOutputStream buf = new ByteArrayOutputStream();
  369. int result = bufferedInputStream.read();
  370. while (result != -1) {
  371. buf.write((byte) result);
  372. result = bufferedInputStream.read();
  373. }
  374. String json = buf.toString();
  375. //转为bugDetail
  376. List<BugDetail> bugDetailList = JSON.parseArray(json, BugDetail.class);
  377. for (BugDetail bugDetail : bugDetailList) {
  378. bugDetail.setOriginalCaseId(originalCaseId);
  379. //修改图片文件路径为oss路径
  380. String imageUrl = bugDetail.getImgUrl();
  381. String[] imageUrlArray = imageUrl.split(",");
  382. StringBuilder stringBuilder = new StringBuilder();
  383. for (String imageUrlStr : imageUrlArray) {
  384. if(!"".equals(imageUrl)) {
  385. String[] filePath = imageUrlStr.split("/");
  386. String fileName = filePath[filePath.length - 1];
  387. String newImageUrl = ossConfig.getBaseUrl() + folderName + "/" + UploadType.IMAGE + originalCaseId + "/" + cpSerialNum + "/" + fileName;
  388. stringBuilder.append(newImageUrl).append(",");
  389. }
  390. }
  391. bugDetail.setImgUrl(stringBuilder.toString());
  392. bugDetailDao.save(bugDetail);
  393. }
  394. //解压图片文件,上传至oss
  395. String destPath= savePath + folderName + inputName + "/imageUnzip/"+originalCaseId+"/"+cpSerialNum;
  396. File unzipFile=new File(destPath);
  397. if(!unzipFile.getParentFile().exists()) { unzipFile.getParentFile().mkdirs(); }
  398. unZip(zipFile,destPath,originalCaseId,cpSerialNum);
  399. return bugDetailList;
  400. } catch (IOException e) {
  401. e.printStackTrace();
  402. }
  403. return new ArrayList<>();
  404. }
  405. private void bugDetailToFile(List<BugDetail> bugDetailList, String caseId) {
  406. String[] titles = {"bug_id", "bug_category", "severity", "recurrent", "bug_create_time", "bug_page", "title",
  407. "description", "img_url",
  408. "score", "parent", "children", "root", "good_num", "good_worker_id", "bad_num", "bad_worker_id",
  409. "test_case_id", "test_case_name", "test_case_front", "test_case_behind", "test_case_description", "test_case_create_time",
  410. "report_id", "report_name", "report_create_time", "script_location", "report_location", "log_location", "device_model", "device_brand", "device_os",
  411. "worker_id",
  412. "case_app_name", "case_paper_type", "case_test_type", "case_description", "case_require_doc",
  413. "case_take_id", "originalCaseId", "cpSerialNum"};
  414. File csvFile = exportCsv(titles, bugDetailList, caseId);
  415. File jsonFile = exportJson(bugDetailList, caseId);
  416. String csvObjectName = folderName.substring(1) + outputName + "/"+caseId+"/"+cpSerialNum+"/" + csvFile.getName();
  417. String jsonObjectName = folderName.substring(1) + outputName + "/"+caseId+"/"+cpSerialNum+"/" + jsonFile.getName();
  418. uploadToOss(csvObjectName,csvFile);
  419. uploadToOss(jsonObjectName,jsonFile);
  420. }
  421. private File exportJson(List<BugDetail> bugDetailList, String caseId) {
  422. try {
  423. File file = new File(savePath + folderName + outputName + "/" + caseId + "/" + caseId + ".json");
  424. if(!file.getParentFile().exists()) { file.getParentFile().mkdirs(); }
  425. JSONArray jsonArray = new JSONArray(bugDetailList);
  426. Writer write = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
  427. write.write(jsonArray.toString());
  428. write.flush();
  429. write.close();
  430. return file;
  431. } catch (IOException e) {
  432. e.printStackTrace();
  433. }
  434. return null;
  435. }
  436. private <T> File exportCsv(String[] titles, List<T> list, String caseId) {
  437. try {
  438. File file = new File(savePath + folderName + outputName + "/" + caseId + "/" + caseId + ".csv");
  439. if(!file.getParentFile().exists()) { file.getParentFile().mkdirs(); }
  440. //构建输出流,同时指定编码
  441. OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
  442. //csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
  443. for (String title : titles) {
  444. ow.write(title);
  445. ow.write(",");
  446. }
  447. //写完文件头后换行
  448. ow.write("\r\n");
  449. //写内容
  450. for (Object obj : list) {
  451. //利用反射获取所有字段
  452. Field[] fields = obj.getClass().getDeclaredFields();
  453. for (Field field : fields) {
  454. //设置字段可见性
  455. field.setAccessible(true);
  456. //防止某个field没有赋值
  457. if (field.get(obj) == null) {
  458. ow.write("");
  459. } else {
  460. //解决csv文件中对于逗号和双引号的转义问题
  461. ow.write("\"" + field.get(obj).toString().replaceAll("\"", "\"\"") + "\"");
  462. }
  463. ow.write(",");
  464. }
  465. //写完一行换行
  466. ow.write("\r\n");
  467. }
  468. ow.flush();
  469. ow.close();
  470. return file;
  471. } catch (IOException | IllegalAccessException e) {
  472. e.printStackTrace();
  473. }
  474. return null;
  475. }
  476. private void uploadToOss(String objectName,File file) {
  477. if (file != null) {
  478. OSS ossClient = ossConfig.ossClient();
  479. OssAliyun.uploadFile(ossClient, ossConfig.getBucketName(), objectName, file);
  480. } else {
  481. System.out.println("file is null");
  482. }
  483. }
  484. /**
  485. * zip解压
  486. *
  487. * @param srcFile zip源文件
  488. * @param destDirPath 解压后的目标文件夹
  489. * @throws RuntimeException 解压失败会抛出运行时异常
  490. */
  491. private void unZip(File srcFile, String destDirPath,String originalCaseId,String fromCpSerialNum) throws RuntimeException {
  492. long start = System.currentTimeMillis();
  493. // 判断源文件是否存在
  494. if (!srcFile.exists()) {
  495. throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
  496. }
  497. // 开始解压
  498. ZipFile zipFile = null;
  499. try {
  500. zipFile = new ZipFile(srcFile);
  501. Enumeration<?> entries = zipFile.entries();
  502. while (entries.hasMoreElements()) {
  503. ZipEntry entry = (ZipEntry) entries.nextElement();
  504. System.out.println("解压" + entry.getName());
  505. // 如果是文件夹,就创建个文件夹
  506. if (entry.isDirectory()) {
  507. String dirPath = destDirPath + "/" + entry.getName();
  508. File dir = new File(dirPath);
  509. dir.mkdirs();
  510. } else {
  511. // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
  512. File targetFile = new File(destDirPath + "/" + entry.getName());
  513. // 保证这个文件的父文件夹必须要存在
  514. if (!targetFile.getParentFile().exists()) {
  515. targetFile.getParentFile().mkdirs();
  516. }
  517. targetFile.createNewFile();
  518. // 将压缩文件内容写入到这个文件中
  519. InputStream is = zipFile.getInputStream(entry);
  520. FileOutputStream fos = new FileOutputStream(targetFile);
  521. int len;
  522. byte[] buf = new byte[BUFFER_SIZE];
  523. while ((len = is.read(buf)) != -1) {
  524. fos.write(buf, 0, len);
  525. }
  526. // 关流顺序,先打开的后关闭
  527. fos.close();
  528. is.close();
  529. //图片文件上传至oss
  530. String objectName = folderName + "/image/"+originalCaseId+"/"+fromCpSerialNum+"/" + targetFile.getName();
  531. uploadToOss(objectName,targetFile);
  532. }
  533. }
  534. long end = System.currentTimeMillis();
  535. System.out.println("解压完成,耗时:" + (end - start) + " ms");
  536. } catch (Exception e) {
  537. throw new RuntimeException("unzip error from ZipUtils", e);
  538. } finally {
  539. if (zipFile != null) {
  540. try {
  541. zipFile.close();
  542. } catch (IOException e) {
  543. e.printStackTrace();
  544. }
  545. }
  546. }
  547. }
  548. private void toZip(String srcDir, OutputStream out, boolean keepDirStructure)
  549. throws RuntimeException {
  550. long start = System.currentTimeMillis();
  551. ZipOutputStream zos = null;
  552. try {
  553. zos = new ZipOutputStream(out);
  554. File sourceFile = new File(srcDir);
  555. compress(sourceFile, zos, sourceFile.getName(), keepDirStructure);
  556. long end = System.currentTimeMillis();
  557. System.out.println("压缩完成,耗时:" + (end - start) + " ms");
  558. } catch (Exception e) {
  559. throw new RuntimeException("zip error from ZipUtils", e);
  560. } finally {
  561. if (zos != null) {
  562. try {
  563. zos.close();
  564. } catch (IOException e) {
  565. e.printStackTrace();
  566. }
  567. }
  568. }
  569. }
  570. /**
  571. * 递归压缩方法
  572. *
  573. * @param sourceFile 源文件
  574. * @param zos zip输出流
  575. * @param name 压缩后的名称
  576. * @param keepDirStructure 是否保留原来的目录结构,true:保留目录结构;
  577. * false:所有文件跑到压缩包根目录下(注意:不保留目录结构可能会出现同名文件,会压缩失败)
  578. * @throws Exception
  579. */
  580. private void compress(File sourceFile, ZipOutputStream zos, String name,
  581. boolean keepDirStructure) throws Exception {
  582. byte[] buf = new byte[BUFFER_SIZE];
  583. if (sourceFile.isFile()) {
  584. // 向zip输出流中添加一个zip实体,构造器中name为zip实体的文件的名字
  585. zos.putNextEntry(new ZipEntry(name));
  586. // copy文件到zip输出流中
  587. int len;
  588. FileInputStream in = new FileInputStream(sourceFile);
  589. while ((len = in.read(buf)) != -1) {
  590. zos.write(buf, 0, len);
  591. }
  592. // Complete the entry
  593. zos.closeEntry();
  594. in.close();
  595. } else {
  596. File[] listFiles = sourceFile.listFiles();
  597. if (listFiles == null || listFiles.length == 0) {
  598. // 需要保留原来的文件结构时,需要对空文件夹进行处理
  599. if (keepDirStructure) {
  600. // 空文件夹的处理
  601. zos.putNextEntry(new ZipEntry(name + "/"));
  602. // 没有文件,不需要文件的copy
  603. zos.closeEntry();
  604. }
  605. } else {
  606. for (File file : listFiles) {
  607. // 判断是否需要保留原来的文件结构
  608. if (keepDirStructure) {
  609. // 注意:file.getName()前面需要带上父文件夹的名字加一斜杠,
  610. // 不然最后压缩包中就不能保留原来的文件结构,即:所有文件都跑到压缩包根目录下了
  611. compress(file, zos, name + "/" + file.getName(), true);
  612. } else {
  613. compress(file, zos, file.getName(), false);
  614. }
  615. }
  616. }
  617. }
  618. }
  619. }