DataService.java 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389
  1. package edu.nju.service;
  2. import com.alibaba.fastjson.JSON;
  3. import com.aliyun.oss.OSS;
  4. import edu.nju.dao.*;
  5. import edu.nju.entities.*;
  6. import edu.nju.util.OssAliyun;
  7. import edu.nju.util.TransUtil;
  8. import org.json.JSONArray;
  9. import org.springframework.beans.factory.annotation.Autowired;
  10. import org.springframework.beans.factory.annotation.Value;
  11. import org.springframework.stereotype.Service;
  12. import org.springframework.web.multipart.MultipartFile;
  13. import java.io.*;
  14. import java.lang.reflect.Field;
  15. import java.net.HttpURLConnection;
  16. import java.net.URL;
  17. import java.net.URLConnection;
  18. import java.nio.charset.StandardCharsets;
  19. import java.util.*;
  20. import java.util.zip.ZipEntry;
  21. import java.util.zip.ZipFile;
  22. /**
  23. * @Author JiaWei Xu
  24. * @Date 2020-12-25 10:45
  25. * @Email xjwhhh233@outlook.com
  26. */
  27. @Service
  28. public class DataService {
  29. private static final int BUFFER_SIZE = 2048;
  30. @Autowired
  31. ExamDao examDao;
  32. @Autowired
  33. BugDao bugDao;
  34. @Autowired
  35. ReportDao reportDao;
  36. @Autowired
  37. TestCaseDao testCaseDao;
  38. @Autowired
  39. CaseToBugDao caseToBugDao;
  40. @Autowired
  41. BugScoreDao bugScoreDao;
  42. @Autowired
  43. BugMirrorDao bugMirrorDao;
  44. @Autowired
  45. BugHistoryDao bugHistoryDao;
  46. @Autowired
  47. BugDetailDao bugDetailDao;
  48. @Value("${cpSerialNum}")
  49. private String cpSerialNum;
  50. private static final String bucketName = "mooctest-site";
  51. private static final String imageUrlPrefix = "https://mooctest-site.oss-cn-shanghai.aliyuncs.com/xinchuang/image/";
  52. /**
  53. * 根据caseId获取对应bug信息
  54. *
  55. * @param caseId
  56. * @return
  57. */
  58. public List<BugDetail> getBugDetailByCaseId(String caseId) {
  59. List<BugDetail> bugDetailList = new ArrayList<>();
  60. Exam crowdCase = examDao.findById(caseId);
  61. if (crowdCase != null) {
  62. List<Report> reportList = reportDao.findByCaseId(caseId);
  63. for (Report report : reportList) {
  64. String reportId = report.getId();
  65. List<TestCase> testCaseList = testCaseDao.findByReport(reportId);
  66. for (TestCase testCase : testCaseList) {
  67. String testCaseId = testCase.getId();
  68. CaseToBug caseToBug = caseToBugDao.findById(testCaseId);
  69. if (caseToBug != null) {
  70. List<String> bugIdList = caseToBug.getBug_id();
  71. for (String bugId : bugIdList) {
  72. BugDetail bugDetail = new BugDetail();
  73. bugDetail.setId(bugId);
  74. //bug基本属性
  75. Bug bug = bugDao.findByid(bugId);
  76. if (bug != null) {
  77. bugDetail.setBugCategory(bug.getBug_category());
  78. bugDetail.setSeverity(TransUtil.severityTransFromInt(bug.getSeverity()));
  79. bugDetail.setRecurrent(TransUtil.recurrentTransFromInt(bug.getRecurrent()));
  80. bugDetail.setBugCreateTime(TransUtil.formatTimeMillis(bug.getCreate_time_millis()));
  81. bugDetail.setBugPage(bug.getBug_page());
  82. bugDetail.setTitle(bug.getTitle());
  83. bugDetail.setBugDescription(bug.getDescription());
  84. bugDetail.setImgUrl(bug.getImg_url());
  85. }
  86. //bugScore属性
  87. BugScore bugScore = bugScoreDao.findById(bugId);
  88. if (bugScore != null) {
  89. bugDetail.setScore(bugScore.getGrade());
  90. }
  91. //bugMirror属性
  92. BugMirror bugMirror = bugMirrorDao.findById(bugId);
  93. if (bugMirror != null) {
  94. Set<String> goodWorkerIdSet = new HashSet<>();
  95. Set<String> badWorkerIdSet = new HashSet<>();
  96. Set<String> goodReportIdSet = bugMirror.getGood();
  97. Set<String> badReportIdSet = bugMirror.getBad();
  98. int goodNum = 0;
  99. int badNum = 0;
  100. for (String goodReportId : goodReportIdSet) {
  101. Report goodReport = reportDao.findById(goodReportId);
  102. if (goodReport != null) {
  103. goodNum++;
  104. goodWorkerIdSet.add(goodReport.getWorker_id());
  105. }
  106. }
  107. for (String badReportId : badReportIdSet) {
  108. Report badReport = reportDao.findById(badReportId);
  109. if (badReport != null) {
  110. badNum++;
  111. badWorkerIdSet.add(badReport.getWorker_id());
  112. }
  113. }
  114. bugDetail.setGoodNum(goodNum);
  115. bugDetail.setBadNum(badNum);
  116. bugDetail.setGoodWorkerId(goodWorkerIdSet);
  117. bugDetail.setBadWorkerId(badWorkerIdSet);
  118. }
  119. //bugHistory属性
  120. BugHistory bugHistory = bugHistoryDao.findByid(bugId);
  121. if (bugHistory != null) {
  122. bugDetail.setParent(bugHistory.getParent());
  123. bugDetail.setChildren(bugHistory.getChildren());
  124. bugDetail.setRoot(bugHistory.getRoot());
  125. }
  126. //testCase属性
  127. bugDetail.setTestCaseId(testCase.getId());
  128. bugDetail.setTestCaseName(testCase.getName());
  129. bugDetail.setTestCaseFront(testCase.getFront());
  130. bugDetail.setTestCaseBehind(testCase.getBehind());
  131. bugDetail.setTestCaseDescription(testCase.getDescription());
  132. bugDetail.setTestCaseCreateTime(TransUtil.formatTimeMillis(testCase.getCreate_time_millis()));
  133. //report属性
  134. bugDetail.setReportId(report.getId());
  135. bugDetail.setReportName(report.getName());
  136. bugDetail.setScriptLocation(report.getScript_location());
  137. bugDetail.setReportLocation(report.getReport_location());
  138. bugDetail.setLogLocation(report.getLog_location());
  139. bugDetail.setDeviceModel(report.getDevice_model());
  140. bugDetail.setDeviceBrand(report.getDevice_brand());
  141. bugDetail.setDeviceOs(report.getDevice_os());
  142. //worker属性
  143. bugDetail.setWorkerId(report.getWorker_id());
  144. //众测任务属性
  145. bugDetail.setCaseAppName(crowdCase.getName());
  146. bugDetail.setCasePaperType(crowdCase.getPaper_type());
  147. bugDetail.setCaseTestType(crowdCase.getTest_type());
  148. bugDetail.setCaseDescription(crowdCase.getDescription());
  149. bugDetail.setCaseRequireDoc("");
  150. bugDetail.setCaseTakeId(report.getCase_take_id());
  151. //cp序列号
  152. bugDetail.setCpSerialNum(cpSerialNum);
  153. bugDetailList.add(bugDetail);
  154. }
  155. }
  156. }
  157. }
  158. }
  159. bugDetailToFile(bugDetailList, caseId);
  160. return bugDetailList;
  161. }
  162. public List<BugDetail> saveBugDetailFromOss(MultipartFile sourceZipFile, MultipartFile sourceJsonFile, String originalCaseId, String cpSerialNum) {
  163. try {
  164. // //从oss下载json文件
  165. // URL url = new URL(jsonFilePath);
  166. // URLConnection urlConnection = url.openConnection();
  167. // HttpURLConnection httpURLConnection = (HttpURLConnection) urlConnection;
  168. // httpURLConnection.setConnectTimeout(1000 * 5);
  169. // httpURLConnection.setRequestProperty("Charset", "UTF-8");
  170. // httpURLConnection.connect();
  171. //读取文件流并保存在本地
  172. String zipFilePath="xinchuangdata/input/imageZip/"+originalCaseId+"/"+cpSerialNum+"/"+originalCaseId+".zip";
  173. File zipFile=new File(zipFilePath);
  174. if(!zipFile.getParentFile().exists()) { zipFile.getParentFile().mkdirs(); }
  175. if(!sourceZipFile.isEmpty()) { sourceZipFile.transferTo(zipFile); }
  176. String jsonFilePath="xinchuangdata/input/"+originalCaseId+"/"+cpSerialNum+"/"+originalCaseId+".json";
  177. File jsonFile=new File(jsonFilePath);
  178. if(!jsonFile.getParentFile().exists()) { jsonFile.getParentFile().mkdirs(); }
  179. if(!sourceJsonFile.isEmpty()) { sourceJsonFile.transferTo(zipFile); }
  180. //读取本地文件
  181. BufferedInputStream bufferedInputStream = new BufferedInputStream(new FileInputStream(jsonFile));
  182. ByteArrayOutputStream buf = new ByteArrayOutputStream();
  183. int result = bufferedInputStream.read();
  184. while (result != -1) {
  185. buf.write((byte) result);
  186. result = bufferedInputStream.read();
  187. }
  188. String json = buf.toString();
  189. //转为bugDetail
  190. List<BugDetail> bugDetailList = JSON.parseArray(json, BugDetail.class);
  191. for (BugDetail bugDetail : bugDetailList) {
  192. bugDetail.setOriginalCaseId(originalCaseId);
  193. //修改图片文件路径为oss路径
  194. String imageUrl = bugDetail.getImgUrl();
  195. String[] imageUrlArray = imageUrl.split(",");
  196. StringBuilder stringBuilder = new StringBuilder();
  197. for (String imageUrlStr : imageUrlArray) {
  198. String[] filePath = imageUrlStr.split("/");
  199. String fileName = filePath[filePath.length - 1];
  200. String newImageUrl = imageUrlPrefix + originalCaseId + "/" + cpSerialNum + "/" + fileName;
  201. stringBuilder.append(newImageUrl).append(",");
  202. }
  203. bugDetail.setImgUrl(stringBuilder.toString());
  204. bugDetailDao.save(bugDetail);
  205. }
  206. //解压图片文件,上传至oss
  207. String destPath="xinchuangdata/input/imageUnzip/"+originalCaseId+"/"+cpSerialNum;
  208. File unzipFile=new File(destPath);
  209. if(!unzipFile.getParentFile().exists()) { unzipFile.getParentFile().mkdirs(); }
  210. unZip(zipFile,destPath,originalCaseId,cpSerialNum);
  211. return bugDetailList;
  212. } catch (IOException e) {
  213. e.printStackTrace();
  214. }
  215. return new ArrayList<>();
  216. }
  217. private void bugDetailToFile(List<BugDetail> bugDetailList, String caseId) {
  218. String[] titles = {"bug_id", "bug_category", "severity", "recurrent", "bug_create_time", "bug_page", "title",
  219. "description", "img_url",
  220. "score", "parent", "children", "root", "good_num", "good_worker_id", "bad_num", "bad_worker_id",
  221. "test_case_id", "test_case_name", "test_case_front", "test_case_behind", "test_case_description", "test_case_create_time",
  222. "report_id", "report_name", "report_create_time", "script_location", "report_location", "log_location", "device_model", "device_brand", "device_os",
  223. "worker_id",
  224. "case_app_name", "case_paper_type", "case_test_type", "case_description", "case_require_doc",
  225. "case_take_id", "originalCaseId", "cpSerialNum"};
  226. File csvFile = exportCsv(titles, bugDetailList, caseId);
  227. File jsonFile = exportJson(bugDetailList, caseId);
  228. // uploadToOss(csvFile);
  229. // uploadToOss(jsonFile);
  230. }
  231. private File exportJson(List<BugDetail> bugDetailList, String caseId) {
  232. try {
  233. File file = new File("data/output/" + caseId + ".json");
  234. JSONArray jsonArray = new JSONArray(bugDetailList);
  235. Writer write = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
  236. write.write(jsonArray.toString());
  237. write.flush();
  238. write.close();
  239. return file;
  240. } catch (IOException e) {
  241. e.printStackTrace();
  242. }
  243. return null;
  244. }
  245. private <T> File exportCsv(String[] titles, List<T> list, String caseId) {
  246. try {
  247. File file = new File("data/output/" + caseId + ".csv");
  248. //构建输出流,同时指定编码
  249. OutputStreamWriter ow = new OutputStreamWriter(new FileOutputStream(file), StandardCharsets.UTF_8);
  250. //csv文件是逗号分隔,除第一个外,每次写入一个单元格数据后需要输入逗号
  251. for (String title : titles) {
  252. ow.write(title);
  253. ow.write(",");
  254. }
  255. //写完文件头后换行
  256. ow.write("\r\n");
  257. //写内容
  258. for (Object obj : list) {
  259. //利用反射获取所有字段
  260. Field[] fields = obj.getClass().getDeclaredFields();
  261. for (Field field : fields) {
  262. //设置字段可见性
  263. field.setAccessible(true);
  264. //防止某个field没有赋值
  265. if (field.get(obj) == null) {
  266. ow.write("");
  267. } else {
  268. //解决csv文件中对于逗号和双引号的转义问题
  269. ow.write("\"" + field.get(obj).toString().replaceAll("\"", "\"\"") + "\"");
  270. }
  271. ow.write(",");
  272. }
  273. //写完一行换行
  274. ow.write("\r\n");
  275. }
  276. ow.flush();
  277. ow.close();
  278. return file;
  279. } catch (IOException | IllegalAccessException e) {
  280. e.printStackTrace();
  281. }
  282. return null;
  283. }
  284. private static void uploadToOss(String objectName,File file) {
  285. if (file != null) {
  286. OSS ossClient = OssAliyun.initShangHaiOss();
  287. OssAliyun.uploadFile(ossClient, bucketName, objectName, file);
  288. } else {
  289. System.out.println("file is null");
  290. }
  291. }
  292. /**
  293. * zip解压
  294. *
  295. * @param srcFile zip源文件
  296. * @param destDirPath 解压后的目标文件夹
  297. * @throws RuntimeException 解压失败会抛出运行时异常
  298. */
  299. public static void unZip(File srcFile, String destDirPath,String originalCaseId,String fromCpSerialNum) throws RuntimeException {
  300. long start = System.currentTimeMillis();
  301. // 判断源文件是否存在
  302. if (!srcFile.exists()) {
  303. throw new RuntimeException(srcFile.getPath() + "所指文件不存在");
  304. }
  305. // 开始解压
  306. ZipFile zipFile = null;
  307. try {
  308. zipFile = new ZipFile(srcFile);
  309. Enumeration<?> entries = zipFile.entries();
  310. while (entries.hasMoreElements()) {
  311. ZipEntry entry = (ZipEntry) entries.nextElement();
  312. System.out.println("解压" + entry.getName());
  313. // 如果是文件夹,就创建个文件夹
  314. if (entry.isDirectory()) {
  315. String dirPath = destDirPath + "/" + entry.getName();
  316. File dir = new File(dirPath);
  317. dir.mkdirs();
  318. } else {
  319. // 如果是文件,就先创建一个文件,然后用io流把内容copy过去
  320. File targetFile = new File(destDirPath + "/" + entry.getName());
  321. // 保证这个文件的父文件夹必须要存在
  322. if (!targetFile.getParentFile().exists()) {
  323. targetFile.getParentFile().mkdirs();
  324. }
  325. targetFile.createNewFile();
  326. // 将压缩文件内容写入到这个文件中
  327. InputStream is = zipFile.getInputStream(entry);
  328. FileOutputStream fos = new FileOutputStream(targetFile);
  329. int len;
  330. byte[] buf = new byte[BUFFER_SIZE];
  331. while ((len = is.read(buf)) != -1) {
  332. fos.write(buf, 0, len);
  333. }
  334. // 关流顺序,先打开的后关闭
  335. fos.close();
  336. is.close();
  337. //图片文件上传至oss
  338. String objectName = "xinchuang/image/"+originalCaseId+"/"+fromCpSerialNum+"/" + targetFile.getName();
  339. uploadToOss(objectName,targetFile);
  340. }
  341. }
  342. long end = System.currentTimeMillis();
  343. System.out.println("解压完成,耗时:" + (end - start) + " ms");
  344. } catch (Exception e) {
  345. throw new RuntimeException("unzip error from ZipUtils", e);
  346. } finally {
  347. if (zipFile != null) {
  348. try {
  349. zipFile.close();
  350. } catch (IOException e) {
  351. e.printStackTrace();
  352. }
  353. }
  354. }
  355. }
  356. // public static void main(String[] args){
  357. // File a=new File("/Users/xujiawei/crowd/crowdsource-backend/data/a.zip");
  358. // unZip(a,"/Users/xujiawei/crowd/crowdsource-backend/data/test","1","test");
  359. // }
  360. }