|
@@ -0,0 +1,144 @@
|
|
|
|
+package cn.com.qmth.examcloud.tool.service.export_exam_capture;
|
|
|
|
+
|
|
|
|
+import cn.com.qmth.examcloud.tool.config.SysProperty;
|
|
|
|
+import cn.com.qmth.examcloud.tool.entity.TaskEntity;
|
|
|
|
+import cn.com.qmth.examcloud.tool.service.CommonService;
|
|
|
|
+import cn.com.qmth.examcloud.tool.service.TaskService;
|
|
|
|
+import cn.com.qmth.examcloud.tool.service.export_exam_capture.vo.ExamCaptureInfo;
|
|
|
|
+import cn.com.qmth.examcloud.tool.utils.FileHelper;
|
|
|
|
+import cn.com.qmth.examcloud.tool.utils.FssHelper;
|
|
|
|
+import cn.com.qmth.examcloud.tool.vo.user.User;
|
|
|
|
+import com.alibaba.excel.EasyExcel;
|
|
|
|
+import com.alibaba.excel.context.AnalysisContext;
|
|
|
|
+import com.alibaba.excel.event.AnalysisEventListener;
|
|
|
|
+import org.slf4j.Logger;
|
|
|
|
+import org.slf4j.LoggerFactory;
|
|
|
|
+import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
+import org.springframework.stereotype.Component;
|
|
|
|
+
|
|
|
|
+import java.io.File;
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
+import java.util.List;
|
|
|
|
+import java.util.concurrent.ExecutorService;
|
|
|
|
+import java.util.concurrent.Executors;
|
|
|
|
+import java.util.concurrent.atomic.AtomicInteger;
|
|
|
|
+
|
|
|
|
+@Component
|
|
|
|
+public class ExportExamCaptureTask implements TaskService {
|
|
|
|
+
|
|
|
|
+ private final static Logger log = LoggerFactory.getLogger(ExportExamCaptureTask.class);
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private SysProperty sysProperty;
|
|
|
|
+
|
|
|
|
+ @Autowired
|
|
|
|
+ private CommonService commonService;
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void start(TaskEntity task) {
|
|
|
|
+ // this.execute(loginUser, task);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ public void execute(User loginUser, String exportDir) {
|
|
|
|
+ // List<ExamCaptureInfo> captures = this.loadDataFromExcel(exportDir + "/ec_oe_exam_sync_capture.xlsx");
|
|
|
|
+ List<ExamCaptureInfo> captures = this.loadDataFromExcel(exportDir + "/ec_oe_exam_capture.xlsx");
|
|
|
|
+ this.downloadImages(captures, exportDir);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private List<ExamCaptureInfo> loadDataFromExcel(String dataFilePath) {
|
|
|
|
+ /*
|
|
|
|
+ select d.id as exam_record_data_id,d.exam_id,d.course_id,c.code as course_code,c.name as course_name,
|
|
|
|
+ d.student_id,d.student_code,s.identity_number,d.student_name,p.file_url
|
|
|
|
+ from ec_oe_exam_sync_capture p
|
|
|
|
+ -- from ec_oe_exam_capture p
|
|
|
|
+ inner join ec_oe_exam_record_data d on p.exam_record_data_id=d.id
|
|
|
|
+ inner join ec_b_course c on c.id=d.course_id
|
|
|
|
+ inner join ec_b_student s on s.id=d.student_id
|
|
|
|
+ where d.exam_id in (676);
|
|
|
|
+ */
|
|
|
|
+
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
+ List<ExamCaptureInfo> list = new ArrayList<>();
|
|
|
|
+ try {
|
|
|
|
+ EasyExcel.read(dataFilePath, ExamCaptureInfo.class, new AnalysisEventListener<ExamCaptureInfo>() {
|
|
|
|
+ @Override
|
|
|
|
+ public void invoke(ExamCaptureInfo data, AnalysisContext analysisContext) {
|
|
|
|
+ list.add(data);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Override
|
|
|
|
+ public void doAfterAllAnalysed(AnalysisContext analysisContext) {
|
|
|
|
+ // ignore
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+ ).sheet().doRead();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
|
+ throw new RuntimeException("Excel内容解析错误,请使用标准模板!");
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ long cost = System.currentTimeMillis() - startTime;
|
|
|
|
+ log.info("【获取抓拍照】 总数:{} 耗时:{}ms", list.size(), cost);
|
|
|
|
+ return list;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void downloadImages(List<ExamCaptureInfo> list, String exportDir) {
|
|
|
|
+ long startTime = System.currentTimeMillis();
|
|
|
|
+ int totalCount = list.size();
|
|
|
|
+ AtomicInteger finishCount = new AtomicInteger(), successCount = new AtomicInteger(), failCount = new AtomicInteger();
|
|
|
|
+ ExecutorService executorService = Executors.newFixedThreadPool(5);
|
|
|
|
+
|
|
|
|
+ for (ExamCaptureInfo info : list) {
|
|
|
|
+ executorService.execute(() -> {
|
|
|
|
+ // 路径规则:/capture/考试ID/科目代码_科目名称/考试记录ID/证件号_考生姓名/抓拍照片名称.jpg
|
|
|
|
+ String savePhotoPath = String.format("%s/capture/%s/%s_%s/%s/%s_%s/%s", exportDir, info.getExamId(),
|
|
|
|
+ info.getCourseCode(), info.getCourseName(), info.getExamRecordDataId(),
|
|
|
|
+ info.getIdentityNumber(), info.getStudentName(),
|
|
|
|
+ FileHelper.getFileName(info.getFileUrl()));
|
|
|
|
+ this.doDownload(info.getFileUrl(), savePhotoPath, successCount, failCount);
|
|
|
|
+ finishCount.incrementAndGet();
|
|
|
|
+
|
|
|
|
+ if (finishCount.get() % 100 == 0) {
|
|
|
|
+ float finishRate = finishCount.get() * 100f / totalCount;
|
|
|
|
+ long cost = Math.max((System.currentTimeMillis() - startTime) / 1000, 1);
|
|
|
|
+ float speed = (float) finishCount.get() / cost;
|
|
|
|
+ log.info("【图片下载】 总数:{} 成功数:{} 失败数:{} 进度:{}% 速度:约{}个每秒 已耗时:{}秒",
|
|
|
|
+ totalCount, successCount.get(), failCount.get(), finishRate, speed, cost);
|
|
|
|
+ }
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ // 停止接受新任务,并等待所有任务完成
|
|
|
|
+ executorService.shutdown();
|
|
|
|
+ while (!executorService.isTerminated()) {
|
|
|
|
+ // ignore
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ float finishRate = finishCount.get() * 100f / totalCount;
|
|
|
|
+ long cost = Math.max((System.currentTimeMillis() - startTime) / 1000, 1);
|
|
|
|
+ float speed = (float) finishCount.get() / cost;
|
|
|
|
+ log.info("【图片下载】 总数:{} 成功数:{} 失败数:{} 进度:{}% 速度:约{}个每秒 已耗时:{}秒",
|
|
|
|
+ totalCount, successCount.get(), failCount.get(), finishRate, speed, cost);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ private void doDownload(String photoUrl, String photoPath, AtomicInteger successCount, AtomicInteger failCount) {
|
|
|
|
+ // String urlPrefix = "https://ecs-test-static.qmth.com.cn";
|
|
|
|
+ String urlPrefix = "https://ecs-static.qmth.com.cn";
|
|
|
|
+ photoUrl = FssHelper.finalFileUrl(photoUrl, urlPrefix);
|
|
|
|
+
|
|
|
|
+ if (new File(photoPath).exists()) {
|
|
|
|
+ log.debug("【已下载】 {} {}", photoPath, photoUrl);
|
|
|
|
+ successCount.incrementAndGet();
|
|
|
|
+ return;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ try {
|
|
|
|
+ FileHelper.saveImageToFile(photoUrl, photoPath);
|
|
|
|
+ successCount.incrementAndGet();
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
+ log.error("【下载错误】 {} err:{}", photoPath, e.getMessage());
|
|
|
|
+ failCount.incrementAndGet();
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|