|
@@ -1,36 +1,25 @@
|
|
|
package cn.com.qmth.examcloud.core.oe.admin.api.controller;
|
|
|
|
|
|
-import cn.com.qmth.examcloud.api.commons.enums.ExamType;
|
|
|
import cn.com.qmth.examcloud.api.commons.security.bean.User;
|
|
|
import cn.com.qmth.examcloud.commons.exception.StatusException;
|
|
|
import cn.com.qmth.examcloud.commons.util.FileUtil;
|
|
|
-import cn.com.qmth.examcloud.commons.util.MD5;
|
|
|
+import cn.com.qmth.examcloud.core.oe.admin.base.Constants;
|
|
|
import cn.com.qmth.examcloud.core.oe.admin.base.utils.Check;
|
|
|
-import cn.com.qmth.examcloud.core.oe.admin.dao.ExamRecordDataRepo;
|
|
|
-import cn.com.qmth.examcloud.core.oe.admin.dao.entity.ExamRecordDataEntity;
|
|
|
-import cn.com.qmth.examcloud.core.oe.admin.service.ExamStudentService;
|
|
|
import cn.com.qmth.examcloud.core.oe.admin.service.OfflineExamService;
|
|
|
import cn.com.qmth.examcloud.core.oe.admin.service.bean.OfflineExamCourseInfo;
|
|
|
import cn.com.qmth.examcloud.core.oe.admin.service.bean.uploadfile.FileInfo;
|
|
|
-import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
|
|
|
-import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
|
|
|
-import cn.com.qmth.examcloud.support.enums.ExamProperties;
|
|
|
-import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
|
|
|
import cn.com.qmth.examcloud.web.config.SystemProperties;
|
|
|
-import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
|
|
|
import cn.com.qmth.examcloud.web.support.ControllerSupport;
|
|
|
import io.swagger.annotations.Api;
|
|
|
import io.swagger.annotations.ApiOperation;
|
|
|
import io.swagger.annotations.ApiParam;
|
|
|
-import org.apache.commons.io.IOUtils;
|
|
|
-import org.apache.commons.lang3.StringUtils;
|
|
|
+import org.apache.commons.codec.digest.DigestUtils;
|
|
|
import org.slf4j.Logger;
|
|
|
import org.slf4j.LoggerFactory;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.web.bind.annotation.*;
|
|
|
import org.springframework.web.multipart.MultipartFile;
|
|
|
|
|
|
-import java.io.*;
|
|
|
import java.util.ArrayList;
|
|
|
import java.util.List;
|
|
|
|
|
@@ -52,22 +41,7 @@ public class OfflineExamController extends ControllerSupport {
|
|
|
private OfflineExamService offlineExamService;
|
|
|
|
|
|
@Autowired
|
|
|
- private ExamRecordDataRepo examRecordDataRepo;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- private ExamStudentService examStudentService;
|
|
|
-
|
|
|
- @Autowired
|
|
|
- SystemProperties systemConfig;
|
|
|
-
|
|
|
- /**
|
|
|
- * 答案文件最大限制
|
|
|
- * 单位:M
|
|
|
- */
|
|
|
- private static int answerMaxsize = 30;
|
|
|
-
|
|
|
- public static final String TEMP_FILE_EXP = "offlineExam/";
|
|
|
-
|
|
|
+ private SystemProperties systemConfig;
|
|
|
|
|
|
/**
|
|
|
* 获取离线考试列表
|
|
@@ -125,120 +99,41 @@ public class OfflineExamController extends ControllerSupport {
|
|
|
public void batchSubmitPaper(@ApiParam(value = "考试记录id") @RequestParam Long examRecordDataId,
|
|
|
@ApiParam(value = "文件类型:ZIP、PDF、IMAGE(单选、三选一)") @RequestParam String fileType,
|
|
|
@ApiParam(value = "文件MD5信息") @RequestParam String[] fileMd5Array,
|
|
|
- @ApiParam(value = "文件数组") @RequestPart MultipartFile[] fileArray) throws Exception {
|
|
|
- Check.isNull(fileArray, "files不能为空");
|
|
|
- Check.isNull(examRecordDataId, "examRecordDataId不能为空");
|
|
|
- if (fileArray.length != fileMd5Array.length) {
|
|
|
- throw new StatusException("200001", "文件数量和文件摘要信息不匹配");
|
|
|
- }
|
|
|
-
|
|
|
- ExamRecordDataEntity examRecordData = GlobalHelper.getEntity(examRecordDataRepo, examRecordDataId, ExamRecordDataEntity.class);
|
|
|
- if (examRecordData.getExamType() != ExamType.OFFLINE) {
|
|
|
- throw new StatusException("100003", "非离线考试");
|
|
|
- }
|
|
|
-
|
|
|
- boolean isEnable = examStudentService.isEnableExamStudent(examRecordData.getExamStudentId());
|
|
|
- if (!isEnable) {
|
|
|
- throw new StatusException("000500", "当前考生已禁用!");
|
|
|
- }
|
|
|
-
|
|
|
- String offlineUploadFileType = ExamCacheTransferHelper.getCachedExamProperty(examRecordData.getExamId(),
|
|
|
- examRecordData.getStudentId(),
|
|
|
- ExamProperties.OFFLINE_UPLOAD_FILE_TYPE.name()).getValue();
|
|
|
- if (StringUtils.isBlank(offlineUploadFileType) || "[]".equals(offlineUploadFileType)) {
|
|
|
- throw new StatusException("OfflineExamController-submitPaper-003", "当前考试设置不允许上传附件");
|
|
|
- }
|
|
|
+ @ApiParam(value = "文件数组") @RequestPart(required = false) MultipartFile[] fileArray) throws Exception {
|
|
|
+ Check.isNull(fileArray, "上传文件不能为空");
|
|
|
+ User user = getAccessUser();
|
|
|
|
|
|
- String upperFileType = fileType.toUpperCase();
|
|
|
- if (("PDF".equals(upperFileType) || "ZIP".equals(upperFileType)) && fileArray.length > 1) {
|
|
|
- StringBuilder sb = new StringBuilder();
|
|
|
- for (int i = 0; i < fileArray.length; i++) {
|
|
|
- MultipartFile file = fileArray[i];
|
|
|
- String fileName = file.getOriginalFilename();
|
|
|
- sb.append(fileName).append(",");
|
|
|
- }
|
|
|
- sb.deleteCharAt(sb.length() - 1);
|
|
|
- log.error("batchSubmitPaper-duplicate:" + examRecordDataId + ":" + sb);
|
|
|
- throw new StatusException("000500", "上传" + upperFileType + "类型文件时只能传一个文件");
|
|
|
+ if (fileArray.length != fileMd5Array.length) {
|
|
|
+ throw new StatusException("400401", "文件数量和文件MD5数量不匹配");
|
|
|
}
|
|
|
|
|
|
- List<File> resultFiles = new ArrayList<>();
|
|
|
+ List<FileInfo> fileInfoList = new ArrayList<>();
|
|
|
for (int i = 0; i < fileArray.length; i++) {
|
|
|
MultipartFile file = fileArray[i];
|
|
|
- String fileName = file.getOriginalFilename();
|
|
|
- int index = fileName.lastIndexOf(".");
|
|
|
- String fileSuffix = fileName.substring(index + 1, fileName.length()).toUpperCase();
|
|
|
+ log.info("OfflineExam file {} - {}", i + 1, file.getOriginalFilename());
|
|
|
|
|
|
- if (!"PDF".equals(upperFileType) && !"ZIP".equals(upperFileType)
|
|
|
- && !"IMAGE".equals(upperFileType)) {
|
|
|
- throw new StatusException("100001", "文件类型不正确");
|
|
|
+ if (file.getSize() > Constants.ANSWER_FILE_MAX_SIZE * Constants.M_SIZE) {
|
|
|
+ throw new StatusException("400402", "文件大小不能超过" + Constants.ANSWER_FILE_MAX_SIZE + "M");
|
|
|
}
|
|
|
|
|
|
- if (!"PDF".equals(fileSuffix) && !"ZIP".equals(fileSuffix)
|
|
|
- && !"JPG".equals(fileSuffix) && !"JPEG".equals(fileSuffix) && !"PNG".equals(fileSuffix)) {
|
|
|
- throw new StatusException("100002", "文件格式不正确");
|
|
|
- }
|
|
|
-
|
|
|
-
|
|
|
- //图片类型特殊处理
|
|
|
- if (fileSuffix.equals("JPG") || fileSuffix.equals("JPEG") || fileSuffix.equals("PNG")) {
|
|
|
- if (offlineUploadFileType.indexOf("IMAGE") < 0) {
|
|
|
- throw new StatusException("100004", "当前考试允许上传文件格式为:" + offlineUploadFileType);
|
|
|
- }
|
|
|
- } else {
|
|
|
- if (offlineUploadFileType.indexOf(fileSuffix) < 0) {
|
|
|
- throw new StatusException("OfflineExamController-submitPaper-004", "当前考试允许上传文件格式为:" + offlineUploadFileType);
|
|
|
- }
|
|
|
+ String realMD5 = DigestUtils.md5Hex(file.getInputStream());
|
|
|
+ String tempMD5 = fileMd5Array[i];
|
|
|
+ if (!realMD5.equals(tempMD5)) {
|
|
|
+ log.warn("realMD5 = {}, tempMD5 = {}", realMD5, tempMD5);
|
|
|
+ throw new StatusException("400403", "文件MD5验证失败");
|
|
|
}
|
|
|
|
|
|
- //判断文件大小
|
|
|
- long fileSize = file.getSize();
|
|
|
-
|
|
|
- if (fileSize > answerMaxsize * 1048576) {
|
|
|
- throw new StatusException("OfflineExamController-submitPaper-005", "文件大小不能超过" + answerMaxsize + "M");
|
|
|
- }
|
|
|
-
|
|
|
- File f = getUploadFile(file);
|
|
|
- String strMd5 = MD5.md5Hex(f);
|
|
|
- String summary = fileMd5Array[i];
|
|
|
- if (!strMd5.equals(summary)) {
|
|
|
- throw new StatusException("OfflineExamController-submitPaper-006", "文件数据不完整,请重新上传");
|
|
|
- }
|
|
|
-
|
|
|
- resultFiles.add(f);
|
|
|
- }
|
|
|
-
|
|
|
- offlineExamService.batchSubmitPaper(examRecordDataId, resultFiles, fileType);
|
|
|
-
|
|
|
- //最后删除临时文件
|
|
|
- for (File tempFile : resultFiles) {
|
|
|
- tempFile.delete();
|
|
|
+ String fileSuffix = FileUtil.getFileSuffix(file.getOriginalFilename());
|
|
|
+ FileInfo fileInfo = new FileInfo();
|
|
|
+ fileInfo.setOriginalFileName(file.getOriginalFilename());
|
|
|
+ fileInfo.setFileBytes(file.getBytes());
|
|
|
+ fileInfo.setFileSize(file.getSize());
|
|
|
+ fileInfo.setFileSuffix(fileSuffix);
|
|
|
+ fileInfo.setMd5(realMD5);
|
|
|
+ fileInfoList.add(fileInfo);
|
|
|
}
|
|
|
- User user = getAccessUser();
|
|
|
- ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(), "考试进度详情-上传作答",
|
|
|
- "考试记录ID:" + examRecordDataId + " 考生ID:" + examRecordData.getExamStudentId()));
|
|
|
- }
|
|
|
|
|
|
- private File getUploadFile(MultipartFile file) {
|
|
|
- //建临时文件夹
|
|
|
- File dirFile = new File(TEMP_FILE_EXP);
|
|
|
- if (!dirFile.exists()) {
|
|
|
- dirFile.mkdirs();
|
|
|
- }
|
|
|
- String fileName = file.getOriginalFilename();
|
|
|
- File tempFile = new File(TEMP_FILE_EXP + fileName);
|
|
|
- OutputStream os = null;
|
|
|
- try {
|
|
|
- os = new FileOutputStream(tempFile);
|
|
|
- IOUtils.copyLarge(file.getInputStream(), os);
|
|
|
- } catch (FileNotFoundException e) {
|
|
|
- e.printStackTrace();
|
|
|
- } catch (IOException e) {
|
|
|
- e.printStackTrace();
|
|
|
- } finally {
|
|
|
- IOUtils.closeQuietly(os);
|
|
|
- }
|
|
|
- return tempFile;
|
|
|
+ offlineExamService.batchSubmitPaper(examRecordDataId, fileInfoList, fileType, user.getUserId());
|
|
|
}
|
|
|
|
|
|
}
|