package com.doumee.api.common; import com.doumee.api.BaseController; import com.doumee.biz.system.SystemDictDataBiz; import com.doumee.core.constants.Constants; import com.doumee.core.model.ApiResponse; import com.doumee.core.utils.DateUtil; import com.doumee.core.utils.aliyun.ALiYunUtil; import io.swagger.annotations.Api; import io.swagger.annotations.ApiImplicitParam; import io.swagger.annotations.ApiImplicitParams; import io.swagger.annotations.ApiOperation; import java.io.*; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Scanner; import java.util.UUID; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import net.lingala.zip4j.core.ZipFile; import net.lingala.zip4j.model.FileHeader; import net.sf.json.JSONObject; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.PostMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.multipart.MultipartFile; import org.springframework.web.multipart.MultipartHttpServletRequest; import org.springframework.web.multipart.commons.CommonsMultipartResolver; /** * 公共接口 * @author 江蹄蹄 * @date 2022/03/15 13:58 */ @RestController @RequestMapping("/public") @Api(tags = "公共接口") public class PublicController extends BaseController { @Autowired private SystemDictDataBiz systemDictDataBiz; /** * 上传 * * @param folder * @param request * @param response * @throws Exception */ @ApiOperation(value = "上传", notes = "上传", httpMethod = "POST", position = 6) @ApiImplicitParams({ @ApiImplicitParam(name = "folder", value = "文件夹 头像:avatar 文件:upload ", required = true, paramType = "query", dataType = "String", dataTypeClass = String.class), }) @PostMapping(value = "/upload", headers = "content-type=multipart/form-data") public ApiResponse uploadMobile(String folder, HttpServletRequest request, HttpServletResponse response) throws Exception { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; return upload(multipartRequest, response, "public/"+folder + "/", systemDictDataBiz.queryByCode(Constants.OSS, Constants.BUCKETNAME).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_ID).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_KEY).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.RESOURCE_PATH).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ENDPOINT).getCode()); } @ApiOperation(value = "富文本文件上传", notes = "富文本文件上传", httpMethod = "POST", position = 6) @ApiImplicitParams({ @ApiImplicitParam(name = "folder", value = "文件夹 头像:avatar 文件:upload ", required = true, paramType = "query", dataType = "String", dataTypeClass = String.class), }) @PostMapping(value = "/uploadRichText", headers = "content-type=multipart/form-data") public ApiResponse uploadRichText( HttpServletRequest request, HttpServletResponse response) throws Exception { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; return upload(multipartRequest, response, "public/upload/", systemDictDataBiz.queryByCode(Constants.OSS, Constants.BUCKETNAME).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_ID).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_KEY).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.RESOURCE_PATH).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ENDPOINT).getCode()); } public ApiResponse upload(HttpServletRequest request, HttpServletResponse response, String folder, String bucketName, String access_id, String access_key, String resourcePath, String endpoint) throws Exception { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); Map context = new HashMap<>(); CommonsMultipartResolver multipartResovler = new CommonsMultipartResolver(); if (multipartResovler.isMultipart(request)) { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; Iterator it = multipartRequest.getFileNames(); while (it.hasNext()) { MultipartFile file = multipartRequest.getFile((String) it.next());// file // multipartRequest.getFile((String) // it.next()); if (file != null) { // 1、上传到服务器临时文件夹 String uploadFileName = file.getOriginalFilename(); String originname = uploadFileName; if (originname.lastIndexOf("/") >= 0) { originname = originname.substring(originname.lastIndexOf("/") + 1); } String nfix = "";// 后缀名 if ( StringUtils.isNotBlank(uploadFileName)) { nfix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); } if ( StringUtils.equalsIgnoreCase(nfix, ".exe")) { context.put("code", 0); context.put("message", "对不起,文件格式\".exe\"上传有误!"); return ApiResponse.failed("对不起,文件格式\".exe\"上传有误!"); } String nowDate = DateUtil.getNowShortDate();// 当前时间(年月日) String fileName = UUID.randomUUID().toString() + nfix; String tempFileName = nowDate + "/" + fileName; String key = folder + tempFileName;// 文件名 ALiYunUtil obs = new ALiYunUtil(endpoint,access_id, access_key); if (obs.uploadOnlineObject(file.getInputStream(),bucketName, key,null)) { // 移动成功,返回文件名 // sendSuccessMessage(response, resourcePath+key); context.put("error", 0); context.put("code", 200); context.put("success", true); context.put("url", resourcePath + key); context.put("imgaddr", tempFileName); context.put("imgname", fileName); context.put("originname", originname); // ApiResponse.writerJson(response, context); return ApiResponse.success(context); } else { // 移动失败 context.put("code", 0); context.put("success", false); context.put("message", "上传失败"); // ApiResponse.writerJson(response, context); return ApiResponse.failed("上传失败"); } } } } context.put("code", 0); context.put("message", "上传失败"); // ApiResponse.writerJson(response, context); return ApiResponse.failed("上传失败"); } /** * 压缩包上传 * * @param request * @param response * @throws Exception */ @ApiOperation(value = "压缩包上传", notes = "上传", httpMethod = "POST", position = 6) @PostMapping(value = "/zipUpload", headers = "content-type=multipart/form-data") public ApiResponse zipUpload(HttpServletRequest request, HttpServletResponse response) throws Exception { MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request; response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); Map context = new HashMap<>(); CommonsMultipartResolver multipartResovler = new CommonsMultipartResolver(); if (multipartResovler.isMultipart(request)) { Iterator it = multipartRequest.getFileNames(); while (it.hasNext()) { MultipartFile file = multipartRequest.getFile((String) it.next());// file // it.next()); if (file != null) { // 1、上传到服务器临时文件夹 String uploadFileName = file.getOriginalFilename(); String originname = uploadFileName; if (originname.lastIndexOf("/") >= 0) { originname = originname.substring(originname.lastIndexOf("/") + 1); } String nfix = "";// 后缀名 if ( StringUtils.isNotBlank(uploadFileName)) { nfix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); } String uuid = UUID.randomUUID().toString(); String fileName = uuid + nfix; File newFile = new File( systemDictDataBiz.queryByCode(Constants.OSS,Constants.TESTCASE_UPLOAD_PATH).getCode() +"/"+fileName); file.transferTo(newFile); return this.Uncompress(systemDictDataBiz.queryByCode(Constants.OSS,Constants.TESTCASE_UPLOAD_PATH).getCode() +"/"+fileName , uuid); } } } return ApiResponse.failed("上传数据文件异常"); } public ApiResponse Uncompress(String filePath,String uuid) { Map test_cases = new LinkedHashMap<>(); String fileSavePath = filePath.replace(".zip","")+"/"; try { File zipFile = new File(filePath); ZipFile zFile = new ZipFile(zipFile);// 首先创建ZipFile指向磁盘上的.zip文件 zFile.setFileNameCharset("GBK"); File destDir = new File(fileSavePath);// 解压目录 zFile.extractAll(fileSavePath); // 将文件抽出到解压目录(解压) List headerList = zFile.getFileHeaders(); List extractedFileList= new ArrayList(); for(FileHeader fileHeader : headerList) { if (!fileHeader.isDirectory()) { System.out.println(fileHeader.getFileName()); extractedFileList.add(new File(destDir,fileHeader.getFileName())); } } File [] extractedFiles = new File[extractedFileList.size()]; extractedFileList.toArray(extractedFiles); Map resultMap = new HashMap<>(); List> resultList = new ArrayList<>(); List> inFileList = new ArrayList<>(); List> outFileList = new ArrayList<>(); Integer inNum = 0; Integer outNum = 0; //处理解压文件 文件名称(无后缀)、文件全名称、文件路径 for(File f:extractedFileList){ String fileName = f.getName(); String destDirFilePath = f.getAbsolutePath(); if(fileName.indexOf(".in")>=0){ inNum = inNum + 1; Map inFileMap = new HashMap<>(); inFileMap.put("fileName",fileName); inFileMap.put("destDirFilePath",destDirFilePath); inFileMap.put("checkName",fileName.replace(".in","")); inFileList.add(inFileMap); }else if(fileName.indexOf(".out")>=0){ outNum = outNum + 1 ; Map outFileMap = new HashMap<>(); outFileMap.put("fileName",fileName); outFileMap.put("destDirFilePath",destDirFilePath); outFileMap.put("checkName",fileName.replace(".out","")); outFileList.add(outFileMap); }else { continue; } } //输入输出文件数量不一致,返回异常 if(inNum != outNum || inNum == 0 ){ return ApiResponse.failed("输入文件与输出文件数量不一致"); } //计算平均分值 默认总分 100分 若存在余数,向上取整 int avgScore = 100/inFileList.size(); if(100 % inFileList.size() > 0){ avgScore = avgScore + 1 ; } int index = 1; //判断输入输出文件名称是否对应,不对应 提示错误信息 Collections.sort(inFileList, new Comparator>() { @Override public int compare(Map o1, Map o2) { if(Integer.valueOf(o1.get("checkName")) > Integer.valueOf(o2.get("checkName"))){ return 1; }else if(Integer.valueOf(o1.get("checkName")) < Integer.valueOf(o2.get("checkName"))){ return -1; } return Integer.valueOf(o2.get("checkName")).compareTo(Integer.valueOf(o1.get("checkName"))); } }); for (Map inMap:inFileList) { //最终返回行数据 Map resultLineMap = new HashMap<>(); resultLineMap.put("input_name",inMap.get("fileName")); resultLineMap.put("score",avgScore); boolean isCheck = false; for (Map outMap:outFileList) { if (inMap.get("checkName").equals(outMap.get("checkName"))){ resultLineMap.put("output_name",outMap.get("fileName")); Map test_cases_data = new HashMap<>(); test_cases_data.put("stripped_output_md5",DigestUtils.md5Hex(readFileContent(fileSavePath + outMap.get("fileName")))); File inFile = new File(inMap.get("destDirFilePath")); File outFile = new File(outMap.get("destDirFilePath")); test_cases_data.put("input_size",inFile.length()); test_cases_data.put("output_size",outFile.length()); test_cases_data.put("input_name",inMap.get("fileName")); test_cases_data.put("output_name",outMap.get("fileName")); test_cases.put(Integer.toString(index),test_cases_data); isCheck = true; break; } } if(!isCheck){ return ApiResponse.failed("未查询到输入文件【" + inMap.get("fileName") +"】对应输出文件"); } resultList.add(resultLineMap); index = index + 1 ; } String infoFilePath = fileSavePath+"info"; //info文件创建 File infoFile = new File(infoFilePath); infoFile.createNewFile(); //info文件写入文件 Map infoMap = new HashMap<>(); infoMap.put("spj",false); infoMap.put("test_cases",test_cases); writeFileContent(infoFilePath, JSONObject.fromObject(infoMap).toString()); resultMap.put("dataList",resultList); resultMap.put("test_case_id",uuid); //删除上传的zip文件(不需要) // zipFile.delete(); //开始异步上传到评测机的ftp服务器 // judgeServerService.startFtpUpload(fileSavePath); return ApiResponse.success(resultMap); }catch(Exception e) { return ApiResponse.failed("文件解压异常"); } } public static String readFileContent(String filePath){ StringBuilder sbd = new StringBuilder(); try (Scanner sc = new Scanner(new FileReader(filePath))) { while (sc.hasNextLine()) { //按行读取字符串 sbd.append(sc.nextLine()+"\n"); } }catch (Exception e){ return "未读取到文件内容"; } String str =sbd.toString(); if(str.endsWith("\n")&& str.length()>0){ //去除末尾空白换行 str = str.substring(0,str.length()-1); } return str.trim(); } /** * 向文件中写入内容 * * @param filepath 文件路径与名称 * @param newstr 写入的内容 * @return * @throws IOException */ public static boolean writeFileContent(String filepath, String newstr) throws IOException { Boolean bool = false; String filein = newstr + "\r\n";//新写入的行,换行 // String temp = ""; // FileInputStream fis = null; // InputStreamReader isr = null; // BufferedReader br = null; // FileOutputStream fos = null; PrintWriter pw = null; try { File file = new File(filepath);//文件路径(包括文件名称) //将文件读入输入流 /* fis = new FileInputStream(file); isr = new InputStreamReader(fis); br = new BufferedReader(isr); //文件原有内容 for (int i = 0; (temp = br.readLine()) != null; i++) { buffer.append(temp); // 行与行之间的分隔符 相当于“\n” buffer = buffer.append(System.getProperty("line.separator")); } buffer.append(filein);*/ StringBuffer buffer = new StringBuffer(filein); // fos = new FileOutputStream(file); pw = new PrintWriter(file); pw.write(buffer.toString().toCharArray()); pw.flush(); bool = true; } catch (Exception e) { // TODO: handle exception e.printStackTrace(); } finally { //不要忘记关闭 if (pw != null) { pw.close(); } /* if (fos != null) { fos.close(); } if (br != null) { br.close(); } if (isr != null) { isr.close(); } if (fis != null) { fis.close(); }*/ } return bool; } /* public ApiResponse uploadBatchFile(HttpServletResponse response, String folder, String bucketName, String access_id, String access_key, String resourcePath, String endpoint,MultipartFile[] files) throws Exception { response.setCharacterEncoding("UTF-8"); response.setContentType("text/html;charset=UTF-8"); Map resultMap = new HashMap<>(); List> listMap = new ArrayList<>(); if (null != files && files.length > 0) { //用于判断文件个数 final int length = files.length; for (MultipartFile file : files) { final String originalFilename = file.getOriginalFilename(); assert originalFilename != null; // 1、上传到服务器临时文件夹 String uploadFileName = file.getOriginalFilename(); String originname = uploadFileName; if (originname.lastIndexOf("/") >= 0) { originname = originname.substring(originname.lastIndexOf("/") + 1); } String nfix = "";// 后缀名 if ( StringUtils.isNotBlank(uploadFileName)) { nfix = uploadFileName.substring(uploadFileName.lastIndexOf(".")); } Map context = new HashMap<>(); if ( StringUtils.equalsIgnoreCase(nfix, ".exe")) { context.put("code", 0); context.put("message", "对不起,文件格式\".exe\"上传有误!"); return ApiResponse.failed("对不起,文件格式\".exe\"上传有误!"); } String nowDate = DateUtil.getNowShortDate();// 当前时间(年月日) String fileName = UUID.randomUUID().toString() + nfix; String tempFileName = nowDate + "/" + fileName; String key = folder + tempFileName;// 文件名 ALiYunUtil obs = new ALiYunUtil(endpoint,access_id, access_key); if (obs.uploadOnlineObject(file.getInputStream(),bucketName, key,null)) { // 移动成功,返回文件名 // sendSuccessMessage(response, resourcePath+key); context.put("error", 0); context.put("code", 200); context.put("success", true); context.put("url", resourcePath + key); context.put("imgaddr", tempFileName); context.put("imgname", fileName); context.put("originname", originname); } else { // 移动失败 resultMap.put("code", 0); resultMap.put("success", false); resultMap.put("message", "上传失败"); } listMap.add(context); } resultMap.put("fileList",listMap); return ApiResponse.success(resultMap); } return ApiResponse.failed("上传失败"); } @ApiOperation(value = "富文本文件上传", notes = "富文本文件上传", httpMethod = "POST", position = 6) @PostMapping(value = "/uploadBatch", headers = "content-type=multipart/form-data") public void uploadBatch( HttpServletRequest request, HttpServletResponse response,MultipartFile[] files) throws Exception { uploadBatchFile(response, "public/upload/", systemDictDataBiz.queryByCode(Constants.OSS, Constants.BUCKETNAME).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_ID).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ACCESS_KEY).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.RESOURCE_PATH).getCode(), systemDictDataBiz.queryByCode(Constants.OSS,Constants.ENDPOINT).getCode(),files); }*/ }