|
@@ -8,10 +8,7 @@ import cn.com.qmth.stmms.ms.collect.dto.LoginDTO;
|
|
|
import cn.com.qmth.stmms.ms.collect.util.OssUploadUtil;
|
|
|
import cn.com.qmth.stmms.ms.commons.config.*;
|
|
|
import cn.com.qmth.stmms.ms.commons.constant.SystemConstant;
|
|
|
-import cn.com.qmth.stmms.ms.commons.utils.CommandUtil;
|
|
|
-import cn.com.qmth.stmms.ms.commons.utils.FileUtil;
|
|
|
-import cn.com.qmth.stmms.ms.commons.utils.MD5Util;
|
|
|
-import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
|
|
|
+import cn.com.qmth.stmms.ms.commons.utils.*;
|
|
|
import cn.com.qmth.stmms.ms.commons.utils.image.ImageCompression;
|
|
|
import cn.com.qmth.stmms.ms.core.cache.ParamCache;
|
|
|
import cn.com.qmth.stmms.ms.core.domain.*;
|
|
@@ -26,6 +23,7 @@ import net.sf.json.JSONObject;
|
|
|
import org.apache.commons.codec.binary.Hex;
|
|
|
import org.apache.commons.codec.digest.DigestUtils;
|
|
|
import org.apache.commons.lang.StringUtils;
|
|
|
+import org.assertj.core.util.Compatibility;
|
|
|
import org.assertj.core.util.Strings;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
@@ -45,6 +43,8 @@ import java.security.MessageDigest;
|
|
|
import java.text.SimpleDateFormat;
|
|
|
import java.util.List;
|
|
|
import java.util.*;
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
+import java.util.concurrent.Executors;
|
|
|
import java.util.concurrent.atomic.AtomicInteger;
|
|
|
import java.util.function.Consumer;
|
|
|
import java.util.stream.Collectors;
|
|
@@ -107,9 +107,14 @@ public class CollectApi {
|
|
|
@Autowired
|
|
|
OssUploadUtil ossUploadUtil;
|
|
|
|
|
|
+ @Autowired
|
|
|
+ OssUtil ossUtil;
|
|
|
+
|
|
|
@Autowired
|
|
|
ImageServerConfig imageServerConfig;
|
|
|
|
|
|
+ ExecutorService executors = Executors.newFixedThreadPool(10);
|
|
|
+
|
|
|
@RequestMapping("user/login")
|
|
|
public LoginDTO login(@RequestParam String loginname, @RequestParam String password) throws Exception {
|
|
|
LoginDTO loginDTO = null;
|
|
@@ -788,10 +793,6 @@ public class CollectApi {
|
|
|
* 分数图片导出
|
|
|
*
|
|
|
* @param imageType
|
|
|
- * @param areaId
|
|
|
- * @param school
|
|
|
- * @param examRoom
|
|
|
- * @param subject
|
|
|
* @param nameRule 1:考号+姓名,2:流水号
|
|
|
* @param startScore
|
|
|
* @param endScore
|
|
@@ -799,42 +800,38 @@ public class CollectApi {
|
|
|
* @throws IOException
|
|
|
*/
|
|
|
@RequestMapping(value = "file/image/exportScorePictures", method = {RequestMethod.GET})
|
|
|
- public String exportScorePictures(@RequestParam(defaultValue = "分数图片") String exportType,
|
|
|
- @RequestParam Long workId,
|
|
|
- @RequestParam String imageType,
|
|
|
- @RequestParam(required = false) Long areaId,
|
|
|
- @RequestParam(required = false) String school,
|
|
|
- @RequestParam(required = false) String examRoom,
|
|
|
- @RequestParam String subject,
|
|
|
- @RequestParam String nameRule,
|
|
|
- @RequestParam(required = false) Integer startScore,
|
|
|
- @RequestParam(required = false) Integer endScore) throws IOException {
|
|
|
+ public void exportScorePictures(@RequestParam(defaultValue = "score-images") String exportType,
|
|
|
+ @RequestParam Long workId,
|
|
|
+ @RequestParam String imageType,
|
|
|
+ @RequestParam String isWatermark,
|
|
|
+ @RequestParam String isResume,
|
|
|
+ @RequestParam String nameRule,
|
|
|
+ @RequestParam(required = false) Integer startScore,
|
|
|
+ @RequestParam(required = false) Integer endScore,
|
|
|
+ @RequestParam String savePath) throws Exception {
|
|
|
+ String[] strings = {"{{workId}}","{{areaCode}}","{{school}}","{{subject}}"};
|
|
|
+ List<String> stringList = Arrays.asList(strings);
|
|
|
+ String[] savePaths = savePath.split("\\\\");
|
|
|
+ for (String string : savePaths) {
|
|
|
+ if(StringUtils.isEmpty(string)){
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ if(!stringList.contains(string)){
|
|
|
+ throw new Exception("文档路径格式不对");
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
if (StringUtils.isBlank(imageType)) {
|
|
|
throw new RuntimeException("请选择图片类型");
|
|
|
}
|
|
|
- if (StringUtils.isBlank(subject)) {
|
|
|
- throw new RuntimeException("请选择科目");
|
|
|
- }
|
|
|
if (StringUtils.isBlank(nameRule)) {
|
|
|
throw new RuntimeException("请选择命名规则");
|
|
|
}
|
|
|
|
|
|
- InputStream inputStream = null;
|
|
|
- OutputStream outputStream = null;
|
|
|
- int count = 0;
|
|
|
try {
|
|
|
//首先根据workId和阶段去查所有试卷
|
|
|
StringBuffer sql = new StringBuffer();
|
|
|
- sql.append("SELECT s.id studentId,s.name studentName, p.work_id workId, p.subject, p.area_code areaCode, p.exam_number examNumber, 0+cast(p.score as char) as score FROM paper p LEFT JOIN student s ON p.work_id = s.work_id AND p.exam_number = s.exam_number WHERE p.score is not null and p.work_id = ").append(workId).append(" AND p.subject = '").append(subject).append("'");
|
|
|
- if (areaId != null) {
|
|
|
- sql.append(" and p.area_code = ").append(areaId);
|
|
|
- }
|
|
|
- if (StringUtils.isNotBlank(school)) {
|
|
|
- sql.append(" and s.school = '").append(school).append("'");
|
|
|
- }
|
|
|
- if (StringUtils.isNotBlank(examRoom)) {
|
|
|
- sql.append(" and s.exam_room = '").append(examRoom).append("'");
|
|
|
- }
|
|
|
+ sql.append("SELECT s.id studentId,s.name studentName,s.school, p.work_id workId, p.subject, p.area_code areaCode, p.exam_number examNumber, 0+cast(p.score as char) as score FROM paper p LEFT JOIN student s ON p.work_id = s.work_id AND p.exam_number = s.exam_number WHERE p.score is not null and p.work_id = ").append(workId);
|
|
|
if (startScore != null && endScore != null) {
|
|
|
sql.append(" and p.score >= ").append(startScore);
|
|
|
sql.append(" and p.score <= ").append(endScore);
|
|
@@ -848,101 +845,156 @@ public class CollectApi {
|
|
|
List<Map<String, Object>> paperList = jdbcTemplate.queryForList(sql.toString());
|
|
|
AtomicInteger atomicInteger = new AtomicInteger(0);
|
|
|
for (Map map : paperList) {
|
|
|
- Long studentId = Long.valueOf(map.get("studentId").toString());
|
|
|
- String studentName = map.get("studentName").toString();
|
|
|
- String subject0 = map.get("subject").toString();
|
|
|
- Subject subject1 = Subject.valueOf(subject0);
|
|
|
- String areaCode = map.get("areaCode").toString();
|
|
|
- String examNumber = map.get("examNumber").toString();
|
|
|
- Double score = Double.parseDouble(map.get("score").toString());
|
|
|
-
|
|
|
- String fileName = examNumber;
|
|
|
- //图片加密、命名规则为随机码的,都是需要md5
|
|
|
- if (ParamCache.paramMap.get(workId).getNameRule() == 1 || ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
|
|
|
- fileName = MD5Util.getImageRuleMd5(workId, subject1.ordinal(), areaCode, examNumber, studentId);
|
|
|
- }
|
|
|
- String path = systemConfig.getSheetDir() + File.separator + workId + File.separator + subject1
|
|
|
- + File.separator + areaCode;
|
|
|
- File file = new File(path + File.separator + fileName + ".jpg");
|
|
|
- //组装导出目录
|
|
|
- StringJoiner expSj = new StringJoiner(File.separator);
|
|
|
- expSj.add(systemConfig.getLocalhostPath()).add("图片导出").add(exportType).add(String.valueOf(workId)).add(subject);
|
|
|
- if (areaId != null) {
|
|
|
- expSj.add(String.valueOf(areaId));
|
|
|
- }
|
|
|
- if (StringUtils.isNotBlank(school)) {
|
|
|
- expSj.add(school);
|
|
|
- }
|
|
|
- if (StringUtils.isNotBlank(examRoom)) {
|
|
|
- expSj.add(examRoom);
|
|
|
- }
|
|
|
- //原图或者水印图
|
|
|
- if (Objects.equals("1", imageType)) {
|
|
|
- expSj.add("sheet");
|
|
|
- } else if (Objects.equals("2", imageType)) {
|
|
|
- expSj.add("watermark");
|
|
|
- }
|
|
|
- //分数
|
|
|
- if (startScore != null && endScore != null) {
|
|
|
- expSj.add(startScore + "-" + endScore);
|
|
|
- } else if (startScore != null && endScore == null) {
|
|
|
- expSj.add(startScore.toString());
|
|
|
- } else if (startScore == null && endScore != null) {
|
|
|
- expSj.add(endScore.toString());
|
|
|
- }
|
|
|
- File out = new File(expSj.toString());
|
|
|
- if (!out.exists()) {
|
|
|
- out.mkdirs();
|
|
|
- }
|
|
|
- //输出命名
|
|
|
- String outFileName;
|
|
|
- if (Objects.equals("1", nameRule)) {
|
|
|
- StringJoiner sj = new StringJoiner("-");
|
|
|
- sj.add(examNumber).add(studentName);
|
|
|
- outFileName = sj.toString();
|
|
|
- } else if (Objects.equals("2", nameRule)) {
|
|
|
- outFileName = String.valueOf(atomicInteger.incrementAndGet());
|
|
|
- } else {
|
|
|
- throw new RuntimeException("命名参数有误");
|
|
|
- }
|
|
|
- File expFile = new File(expSj.toString() + File.separator + outFileName + ".jpg");
|
|
|
- //水印图片
|
|
|
- if (Objects.equals("1", imageType)) {
|
|
|
- //读取指定路径下面的文件
|
|
|
- inputStream = new FileInputStream(file);
|
|
|
- outputStream = new FileOutputStream(expFile);
|
|
|
- if (ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
|
|
|
- outputStream = SystemConstant.writeStream(inputStream, outputStream);
|
|
|
- } else {
|
|
|
- outputStream = SystemConstant.writeStreamFomal(inputStream, outputStream);
|
|
|
+ LOGGER.info("==========================导出分数图片开始,共{}数据================================", paperList.size());
|
|
|
+ executors.submit(() -> {
|
|
|
+ InputStream inputStream = null;
|
|
|
+ OutputStream outputStream = null;
|
|
|
+ long start = System.currentTimeMillis();
|
|
|
+ try {
|
|
|
+ Long studentId = Long.valueOf(map.get("studentId").toString());
|
|
|
+ String studentName = map.get("studentName").toString();
|
|
|
+ String subject = map.get("subject").toString();
|
|
|
+ Subject subject1 = Subject.valueOf(subject);
|
|
|
+ String areaCode = map.get("areaCode").toString();
|
|
|
+ String school = String.valueOf(map.get("school"));
|
|
|
+ String examNumber = map.get("examNumber").toString();
|
|
|
+ Double score = Double.parseDouble(map.get("score").toString());
|
|
|
+
|
|
|
+ String fileName = examNumber;
|
|
|
+ //图片加密、命名规则为随机码的,都是需要md5
|
|
|
+ if (ParamCache.paramMap.get(workId).getNameRule() == 1 || ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
|
|
|
+ fileName = MD5Util.getImageRuleMd5(workId, subject1.ordinal(), areaCode, examNumber, studentId);
|
|
|
+ }
|
|
|
+
|
|
|
+ //组装导出目录
|
|
|
+ StringJoiner expSj = new StringJoiner(File.separator);
|
|
|
+ expSj.add(systemConfig.getLocalhostPath()).add("image-export").add(exportType);
|
|
|
+ //原图或者裁切图
|
|
|
+ String imageTypeStr = Objects.equals("1", imageType) ? "sheet" : Objects.equals("2", imageType) ? "images" : "default";
|
|
|
+ //是否水印
|
|
|
+ String waterTypeStr = Objects.equals("1", isWatermark) ? "yes" : Objects.equals("0", isWatermark) ? "no" : "default";
|
|
|
+ expSj.add(imageTypeStr.concat("-").concat(waterTypeStr));
|
|
|
+ LOGGER.info("{},【{}】开始导出,参数:图片类型:{},是否有水印:{},是否续传:{},命名规则:{}",examNumber, studentName,imageTypeStr, waterTypeStr, isResume == "1"?"是":"否", nameRule == "1"?"考号+姓名":"流水号");
|
|
|
+ //是否加水印
|
|
|
+ for (String spath : savePaths) {
|
|
|
+ if (stringPath("workId").equals(spath)) {
|
|
|
+ expSj.add(String.valueOf(workId));
|
|
|
+ }
|
|
|
+ if (stringPath("areaCode").equals(spath)) {
|
|
|
+ expSj.add(areaCode);
|
|
|
+ }
|
|
|
+ if (stringPath("school").equals(spath)) {
|
|
|
+ expSj.add(school);
|
|
|
+ }
|
|
|
+ if (stringPath("subject").equals(spath)) {
|
|
|
+ expSj.add(subject);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ File out = new File(expSj.toString());
|
|
|
+ if (!out.exists()) {
|
|
|
+ out.mkdirs();
|
|
|
+ }
|
|
|
+ //输出命名
|
|
|
+ String outFileName;
|
|
|
+ if (Objects.equals("1", nameRule)) {
|
|
|
+ StringJoiner sj = new StringJoiner("-");
|
|
|
+ sj.add(examNumber).add(studentName);
|
|
|
+ outFileName = sj.toString();
|
|
|
+ } else if (Objects.equals("2", nameRule)) {
|
|
|
+ outFileName = String.valueOf(atomicInteger.incrementAndGet());
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException("命名参数有误");
|
|
|
+ }
|
|
|
+
|
|
|
+ String path;
|
|
|
+ String dir;
|
|
|
+ if (Objects.equals("1", imageType)) {
|
|
|
+ path = systemConfig.getSheetDir() + File.separator + workId + File.separator + subject1
|
|
|
+ + File.separator + areaCode;
|
|
|
+ dir = systemConfig.getSheetDir();
|
|
|
+ } else if (Objects.equals("2", imageType)) {
|
|
|
+ path = systemConfig.getImageDir() + File.separator + workId + File.separator + subject1
|
|
|
+ + File.separator + areaCode;
|
|
|
+ dir = systemConfig.getImageDir();
|
|
|
+ } else {
|
|
|
+ throw new RuntimeException("图片类型有误");
|
|
|
+ }
|
|
|
+
|
|
|
+ String outFile = expSj.toString() + File.separator + outFileName + ".jpg";
|
|
|
+ if (imageServerConfig.isAliyunOss()) {
|
|
|
+ //是否断点续传
|
|
|
+ if (Objects.equals("1", isResume) && new File(outFile).exists()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ StringJoiner ossSavePath = new StringJoiner("/").add(imageServerConfig.getDir()).add(dir.replace("\\", "/")).add(String.valueOf(workId)).add(subject).add(areaCode);
|
|
|
+ String saveFileName = fileName + ".jpg";
|
|
|
+ String saveFile = ossSavePath.toString().concat("/").concat(saveFileName);
|
|
|
+ if (Objects.equals("0", isWatermark)) {
|
|
|
+ ossUtil.ossDownload(saveFile, outFile);
|
|
|
+ }
|
|
|
+ //下载临时原图
|
|
|
+ if (Objects.equals("1", isWatermark)) {
|
|
|
+ String outSheetFile = expSj.toString() + File.separator + outFileName + "_" + start + ".jpg";
|
|
|
+ File sheetFileTemp = ossUtil.ossDownload(saveFile, outSheetFile);
|
|
|
+ File expFile = new File(outFile);
|
|
|
+ //生成分数水印图片
|
|
|
+ BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
|
|
|
+ Thumbnails.of(sheetFileTemp).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
|
|
|
+ sheetFileTemp.delete();
|
|
|
+ }
|
|
|
+ } else {
|
|
|
+ File file = new File(path + File.separator + fileName + ".jpg");
|
|
|
+ File expFile = new File(outFile);
|
|
|
+ //是否断点续传
|
|
|
+ if (Objects.equals("1", isResume) && expFile.exists()) {
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ if (Objects.equals("0", isWatermark)) {
|
|
|
+ //读取指定路径下面的文件
|
|
|
+ inputStream = new FileInputStream(file);
|
|
|
+ outputStream = new FileOutputStream(expFile);
|
|
|
+ if (ParamCache.paramMap.get(workId).getImageEncrypt() == 1) {
|
|
|
+ outputStream = SystemConstant.writeStream(inputStream, outputStream);
|
|
|
+ } else {
|
|
|
+ outputStream = SystemConstant.writeStreamFomal(inputStream, outputStream);
|
|
|
+ }
|
|
|
+ inputStream.close();
|
|
|
+ outputStream.flush();
|
|
|
+ outputStream.close();
|
|
|
+ }
|
|
|
+ if (Objects.equals("1", isWatermark)) {
|
|
|
+ //生成分数水印图片
|
|
|
+ BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
|
|
|
+ Thumbnails.of(file).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ long end = System.currentTimeMillis();
|
|
|
+ LOGGER.info("{},【{}】结束导出,总耗时:{}秒", examNumber, studentName, (end-start)/1000);
|
|
|
+ } catch (Exception e) {
|
|
|
+ LOGGER.info("{},【{}】导出失败");
|
|
|
+ } finally {
|
|
|
+ try {
|
|
|
+ //强制将缓存区的数据进行输出
|
|
|
+ if (Objects.nonNull(outputStream)) {
|
|
|
+ outputStream.flush();
|
|
|
+ //关流
|
|
|
+ outputStream.close();
|
|
|
+ }
|
|
|
+ if (Objects.nonNull(inputStream)) {
|
|
|
+ inputStream.close();
|
|
|
+ }
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+
|
|
|
+ }
|
|
|
}
|
|
|
- inputStream.close();
|
|
|
- outputStream.flush();
|
|
|
- outputStream.close();
|
|
|
- }
|
|
|
- if (Objects.equals("2", imageType)) {
|
|
|
- //生成分数水印图片
|
|
|
- BufferedImage watermarkImage = createWaterImage(score.intValue() + "分");
|
|
|
- Thumbnails.of(file).scale(0.8).watermark(Positions.BOTTOM_CENTER, watermarkImage, 1f).toFile(expFile);
|
|
|
- }
|
|
|
- count++;
|
|
|
+ });
|
|
|
+ LOGGER.info("==========================导出分数图片结束================================");
|
|
|
|
|
|
- LOGGER.info("studentId:{},subjdect:{},md5:{}", studentId, subject1, fileName);
|
|
|
}
|
|
|
} catch (Exception e) {
|
|
|
e.printStackTrace();
|
|
|
- } finally {
|
|
|
- //强制将缓存区的数据进行输出
|
|
|
- if (Objects.nonNull(outputStream)) {
|
|
|
- outputStream.flush();
|
|
|
- //关流
|
|
|
- outputStream.close();
|
|
|
- }
|
|
|
- if (Objects.nonNull(inputStream)) {
|
|
|
- inputStream.close();
|
|
|
- }
|
|
|
}
|
|
|
- return "导出照片成功,共导出了" + count + "张照片";
|
|
|
}
|
|
|
|
|
|
|
|
@@ -1092,6 +1144,12 @@ public class CollectApi {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ private String stringPath(String s) {
|
|
|
+ StringJoiner stringJoiner = new StringJoiner("", "{{", "}}");
|
|
|
+ stringJoiner.add(s);
|
|
|
+ return stringJoiner.toString();
|
|
|
+ }
|
|
|
+
|
|
|
public static void main(String[] args) throws IOException {
|
|
|
String msg1 = "90分";
|
|
|
BufferedImage bi = createWaterImage(msg1);
|