浏览代码

upgrade fss api...

deason 11 月之前
父节点
当前提交
5c5f95ae96

+ 9 - 9
examcloud-core-oe-student-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/student/api/controller/ExamCaptureController.java

@@ -19,7 +19,7 @@ import cn.com.qmth.examcloud.support.enums.ExamRecordStatus;
 import cn.com.qmth.examcloud.support.examing.ExamRecordData;
 import cn.com.qmth.examcloud.support.examing.ExamingSession;
 import cn.com.qmth.examcloud.support.examing.ExamingStatus;
-import cn.com.qmth.examcloud.web.filestorage.YunHttpRequest;
+import cn.com.qmth.examcloud.support.fss.model.FssSignInfo;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -77,7 +77,7 @@ public class ExamCaptureController extends ControllerSupport {
 
         long startTime = System.currentTimeMillis();
         User user = getAccessUser();
-        validateUpyunSign(signIdentifier, fileUrl, user.getUserId());
+        validateSign(signIdentifier, fileUrl, user.getUserId());
 
         StudentCacheBean studentCache = CacheHelper.getStudent(user.getUserId());
         String baseFaceToken = studentCache.getFaceToken();
@@ -136,23 +136,23 @@ public class ExamCaptureController extends ControllerSupport {
     }
 
     /**
-     * 校验又拍云签名
+     * 校验签名
      *
      * @param signIdentifier 签名标识
      * @param fileUrl        文件路径
      * @param userId         用户id
      */
-    private void validateUpyunSign(String signIdentifier, String fileUrl, Long userId) {
+    private void validateSign(String signIdentifier, String fileUrl, Long userId) {
         //		if (StringUtils.isBlank(signIdentifier)){
         //			throw new StatusException("300001", "签名标识不能为空");
         //		}
         if (!StringUtils.isBlank(signIdentifier)) {
-            String upyunSignRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN + userId + "_" + signIdentifier;
-            YunHttpRequest upYunHttpRequest = redisClient.get(upyunSignRedisKey, YunHttpRequest.class);
-            if (upYunHttpRequest == null) {
+            String signRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN + userId + "_" + signIdentifier;
+            FssSignInfo signInfo = redisClient.get(signRedisKey, FssSignInfo.class);
+            if (signInfo == null) {
                 throw new StatusException("301003", "无效的请求,请检查签名标识");
             }
-            if (!upYunHttpRequest.getAccessUrl().equals(fileUrl)) {
+            if (!signInfo.getAccessUrl().equals(fileUrl)) {
                 throw new StatusException("301004", "文件路径格式不正确");
             }
         }
@@ -228,7 +228,7 @@ public class ExamCaptureController extends ControllerSupport {
                 LOGGER.warn("虚拟摄像头信息格式不正确!" + req.getCameraInfos());
             }
         }
-        validateUpyunSign(req.getSignIdentifier(), req.getFileUrl(), user.getUserId());
+        validateSign(req.getSignIdentifier(), req.getFileUrl(), user.getUserId());
 
         return examCaptureQueueService.saveExamCaptureQueue(req, user.getUserId());
     }

+ 64 - 183
examcloud-core-oe-student-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/student/api/controller/ExamControlController.java

@@ -2,7 +2,7 @@ package cn.com.qmth.examcloud.core.oe.student.api.controller;
 
 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.Util;
+import cn.com.qmth.examcloud.core.oe.student.base.OeConstants;
 import cn.com.qmth.examcloud.core.oe.student.base.utils.Check;
 import cn.com.qmth.examcloud.core.oe.student.bean.*;
 import cn.com.qmth.examcloud.core.oe.student.bean.client.CourseInfo;
@@ -13,19 +13,14 @@ import cn.com.qmth.examcloud.support.Constants;
 import cn.com.qmth.examcloud.support.enums.FileAnswerAcknowledgeStatus;
 import cn.com.qmth.examcloud.support.examing.ExamFileAnswer;
 import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
+import cn.com.qmth.examcloud.support.fss.model.FssSignInfo;
 import cn.com.qmth.examcloud.support.redis.RedisKeyHelper;
-import cn.com.qmth.examcloud.web.filestorage.FileStorageHelper;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.FileStorageType;
-import cn.com.qmth.examcloud.web.filestorage.YunHttpRequest;
 import cn.com.qmth.examcloud.web.helpers.SequenceLockHelper;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import cn.com.qmth.examcloud.web.support.Naked;
-import cn.com.qmth.examcloud.web.upyun.UpyunPathEnvironmentInfo;
-import cn.com.qmth.examcloud.web.upyun.UpyunService;
-import com.google.common.collect.Maps;
 import com.mysql.cj.util.StringUtils;
 import io.swagger.annotations.Api;
 import io.swagger.annotations.ApiOperation;
@@ -39,10 +34,6 @@ import org.springframework.web.bind.annotation.*;
 
 import javax.servlet.http.HttpServletRequest;
 import javax.validation.Valid;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Map;
-import java.util.concurrent.TimeUnit;
 
 @Api(tags = "在线考试控制")
 @RestController
@@ -64,9 +55,6 @@ public class ExamControlController extends ControllerSupport {
     @Autowired
     private ExamFileAnswerService examFileAnswerService;
 
-    @Autowired
-    private UpyunService upyunService;
-
     @Autowired
     private RedisClient redisClient;
 
@@ -212,87 +200,60 @@ public class ExamControlController extends ControllerSupport {
         return examControlService.getEndExamInfo(examRecordDataId);
     }
 
-    /**
-     * 获取又拍云文件上传签名(微信小程序调用)
-     */
     @Deprecated
-    @ApiOperation(value = "获取又拍云文件上传签名(微信小程序调用,废弃)")
+    @ApiOperation(value = "获取作答文件上传签名-又拍云(微信小程序调用,废弃)")
     @PostMapping("/upyunSignature")
-    public UpyunSignatureInfo getUpyunSignature(@ModelAttribute @Valid GetYunSignatureReq req) {
-        return examControlService.getUpyunSignature(req);
+    public FssSignInfo getUpyunSignature(@ModelAttribute @Valid GetYunSignatureReq req) {
+        return getAnswerUploadSign(req);
     }
 
-    /**
-     * 获取云存储上传签名(微信小程序调用)
-     */
-    @ApiOperation(value = "获取文件上传签名(微信小程序调用)")
+    @ApiOperation(value = "获取作答文件上传签名(微信小程序调用)")
     @PostMapping("/yunSignature")
-    public GetYunSignDomain getYunSignature(@ModelAttribute @Valid GetYunSignatureReq req) {
-        FileStorageType fileStorageType = FileStorageUtil.getFileStorageType();
-
-        // 是否为环境监测场景
-        boolean isTestDev = Constants.OE_ENV_CHECK_EXAM_RECORD_DATA_ID.equals(req.getExamRecordDataId());
+    public FssSignInfo getYunSignature(@ModelAttribute @Valid GetYunSignatureReq req) {
+        return getAnswerUploadSign(req);
+    }
 
-        if (FileStorageType.UPYUN.equals(fileStorageType)) {
-            GetUpyunSignDomain result = new GetUpyunSignDomain();
-            Map<String, String> params = Maps.newHashMap();
-            UpyunSignatureInfo info = examControlService.getUpyunSignature(req);
-            String signIdentifier = String.valueOf(System.currentTimeMillis());
-            params.put("authorization", info.getSignature());
-            params.put("policy", info.getPolicy());
-            result.setAccessUrl(FileStorageHelper.getUrl(info.getUpyunFileDomain(), info.getFilePath()));
-            result.setFormUrl(info.getUploadUrl());
-            result.setFormParams(params);
-            result.setSignIdentifier(signIdentifier);
-            return result;
+    private FssSignInfo getAnswerUploadSign(GetYunSignatureReq req) {
+        String fileSuffix = req.getFileSuffix();
+        if (StringUtils.isNullOrEmpty(fileSuffix)) {
+            throw new StatusException("5002", "文件后缀名不允许为空");
         }
+        fileSuffix = !fileSuffix.contains(".") ? "." + fileSuffix : fileSuffix;
 
-        if (FileStorageType.ALIYUN.equals(fileStorageType)) {
-            String fileSuffix = req.getFileSuffix();
-            if (StringUtils.isNullOrEmpty(fileSuffix)) {
-                throw new StatusException("5002", "文件后缀名不允许为空");
+        Long examStudentId;
+        // 是否为环境监测场景
+        boolean isTestDev = Constants.OE_ENV_CHECK_EXAM_RECORD_DATA_ID.equals(req.getExamRecordDataId());
+        if (isTestDev) {
+            examStudentId = Constants.OE_ENV_CHECK_EXAM_STUDENT_ID;
+        } else {
+            ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(req.getExamRecordDataId());
+            if (examRecordData == null) {
+                log.warn("ExamRecordDataCache not exist! examRecordDataId = {}", req.getExamRecordDataId());
+                throw new StatusException("5002", "请求参数值有误!");
             }
-            fileSuffix = !fileSuffix.contains(".") ? "." + fileSuffix : fileSuffix;
+            examStudentId = examRecordData.getExamStudentId();
+        }
 
-            Long examStudentId;
-            if (isTestDev) {
-                examStudentId = Constants.OE_ENV_CHECK_EXAM_STUDENT_ID;
-            } else {
-                ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(req.getExamRecordDataId());
-                if (examRecordData == null) {
-                    log.warn("ExamRecordDataCache not exist! examRecordDataId = {}", req.getExamRecordDataId());
-                    throw new StatusException("5002", "请求参数值有误!");
-                }
-                examStudentId = examRecordData.getExamStudentId();
-            }
+        // 路径:/oe-answer-file/{examStudentId}/{examRecordDataId}/{order}/{examStudentId}_{examRecordDataId}_{order}_{timeMillis}{randomNum}.jpg",
+        StringBuilder filePath = new StringBuilder();
+        filePath.append(OE_ANSWER_FILE_PATH).append(SEPARATOR)
+                .append(examStudentId).append(SEPARATOR).append(req.getExamRecordDataId())
+                .append(SEPARATOR).append(req.getOrder()).append(SEPARATOR)
+                .append(examStudentId).append(UNDERLINE).append(req.getExamRecordDataId())
+                .append(UNDERLINE).append(req.getOrder()).append(UNDERLINE).append(System.currentTimeMillis())
+                .append(RandomUtils.nextInt(8999) + 1000);
+
+        if (!StringUtils.isNullOrEmpty(req.getExt())) {
+            filePath.append(UNDERLINE).append(req.getExt());
+        }
+        filePath.append(fileSuffix);
 
-            StringBuffer filePath = new StringBuffer();
-            filePath.append(OE_ANSWER_FILE_PATH).append(SEPARATOR)
-                    .append(examStudentId).append(SEPARATOR).append(req.getExamRecordDataId())
-                    .append(SEPARATOR).append(req.getOrder()).append(SEPARATOR)
-                    .append(examStudentId).append(UNDERLINE).append(req.getExamRecordDataId())
-                    .append(UNDERLINE).append(req.getOrder()).append(UNDERLINE).append(System.currentTimeMillis())
-                    .append(RandomUtils.nextInt(8999) + 1000);
+        FssSignInfo result = FssFactory.getInstance(false).buildSign(filePath.toString());
 
-            if (!StringUtils.isNullOrEmpty(req.getExt())) {
-                filePath.append(UNDERLINE).append(req.getExt());
-            }
-            filePath.append(fileSuffix);
-
-            GetAliyunSignDomain result = new GetAliyunSignDomain();
-            String signIdentifier = String.valueOf(System.currentTimeMillis());
-            FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            env.setRelativePath(filePath.toString());
-
-            YunHttpRequest aliYunHttpRequest = FileStorageUtil.getSignature(FileStorageType.ALIYUN, Constants.MINI_PROGRAM_ANWSER_SITEID, env, req.getFileMd5());
-            result.setAccessUrl(aliYunHttpRequest.getAccessUrl());
-            result.setFormUrl(aliYunHttpRequest.getFormUrl());
-            result.setFormParams(aliYunHttpRequest.getFormParams());
-            result.setSignIdentifier(signIdentifier);
-            return result;
-        }
+        String signIdentifier = String.valueOf(System.currentTimeMillis());
+        result.setSignIdentifier(signIdentifier);
 
-        throw new StatusException("5002", "未配置正确云存储类型");
+        return result;
     }
 
     /**
@@ -326,11 +287,11 @@ public class ExamControlController extends ControllerSupport {
             String fileUrl = "";
             if (req.getFilePath().indexOf(",") > -1) {
                 for (String url : req.getFilePath().split(",")) {
-                    fileUrl += FileStorageUtil.realPath(url) + ",";
+                    fileUrl += FssHelper.finalFileUrl(url) + ",";
                 }
                 fileUrl = fileUrl.substring(0, fileUrl.length() - 1);
             } else {
-                fileUrl = FileStorageUtil.realPath(req.getFilePath());
+                fileUrl = FssHelper.finalFileUrl(req.getFilePath());
             }
             examControlService.sendFileAnswerToWebSocket(req.getExamRecordDataId(), req.getOrder(),
                     fileUrl, req.getTransferFileType(), user.getUserId(), user.getRootOrgId());
@@ -373,115 +334,35 @@ public class ExamControlController extends ControllerSupport {
     }
 
     @Deprecated
-    @ApiOperation(value = "获取抓拍照片的又拍云签名(废弃)")
+    @ApiOperation(value = "获取抓拍照片文件上传签名信息-又拍云(废弃)")
     @GetMapping("/getCapturePhotoUpYunSign")
-    public GetUpyunSignDomain getCapturePhotoUpYunSign(GetYunSignDomainQuery query) {
-        return getUpYunSign(query);
+    public FssSignInfo getCapturePhotoUpYunSign(GetYunSignDomainQuery query) {
+        return getCaptureUploadSign(query);
     }
 
-    //又拍云签名
-    private GetUpyunSignDomain getUpYunSign(GetYunSignDomainQuery query) {
-        String fileSuffix = query.getFileSuffix();
-        if (StringUtils.isNullOrEmpty(fileSuffix)) {
-            throw new StatusException("200001", "文件后缀名不允许为空");
-        }
-        fileSuffix = fileSuffix.indexOf(".") == -1 ? "." + fileSuffix : fileSuffix;
-
-        GetUpyunSignDomain result = new GetUpyunSignDomain();
-        User accessUser = this.getAccessUser();
-        String signIdentifier = String.valueOf(System.currentTimeMillis());
-        String upyunSignRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN
-                + accessUser.getUserId() + "_" + signIdentifier;
-
-        UpyunPathEnvironmentInfo env = new UpyunPathEnvironmentInfo();
-        env.setRootOrgId(accessUser.getRootOrgId().toString());
-        env.setUserId(accessUser.getUserId().toString());
-        env.setFileSuffix(fileSuffix);
-        YunHttpRequest upYunHttpRequest = upyunService.buildUpYunHttpRequest(Constants.CAPTURE_PHOTO_UPYUN_SITEID, env, query.getFileMd5());
-        redisClient.set(upyunSignRedisKey, upYunHttpRequest, 60);
-        result.setAccessUrl(upYunHttpRequest.getAccessUrl());
-        result.setFormUrl(upYunHttpRequest.getFormUrl());
-        result.setFormParams(upYunHttpRequest.getFormParams());
-        result.setSignIdentifier(signIdentifier);
-        return result;
-    }
-
-    @ApiOperation(value = "获取抓拍照片的云存储签名")
+    @ApiOperation(value = "获取抓拍照片文件上传签名信息")
     @GetMapping("/getCapturePhotoYunSign")
-    public GetYunSignDomain getCapturePhotoYunSign(GetYunSignDomainQuery query) {
-        if (FileStorageType.UPYUN.equals(FileStorageUtil.getFileStorageType())) {
-            return getUpYunSign(query);
-        }
-        if (FileStorageType.ALIYUN.equals(FileStorageUtil.getFileStorageType())) {
-            return getAliYunSign(query);
-        }
-        throw new StatusException("3002", "未配置正确云存储类型");
+    public FssSignInfo getCapturePhotoYunSign(GetYunSignDomainQuery query) {
+        return getCaptureUploadSign(query);
     }
 
-    //阿里云签名
-    private GetAliyunSignDomain getAliYunSign(GetYunSignDomainQuery query) {
-        String fileSuffix = query.getFileSuffix();
-        if (StringUtils.isNullOrEmpty(fileSuffix)) {
+    private FssSignInfo getCaptureUploadSign(GetYunSignDomainQuery query) {
+        User accessUser = this.getAccessUser();
+        if (StringUtils.isNullOrEmpty(query.getFileSuffix())) {
             throw new StatusException("4001", "文件后缀名不允许为空");
         }
-        fileSuffix = fileSuffix.indexOf(".") == -1 ? "." + fileSuffix : fileSuffix;
 
-        GetAliyunSignDomain result = new GetAliyunSignDomain();
-        User accessUser = this.getAccessUser();
+        String fileSuffix = query.getFileSuffix().startsWith(".") ? query.getFileSuffix() : "." + query.getFileSuffix();
+
+        // 路径:/capture_photo/{rootOrgId}/{userId}/{timeMillis}{fileSuffix}
+        String filePath = String.format(OeConstants.CAPTURE_PHOTO_PATH, accessUser.getRootOrgId(), accessUser.getUserId(), System.currentTimeMillis(), fileSuffix);
+        FssSignInfo result = FssFactory.getInstance(false).buildSign(filePath);
+
         String signIdentifier = String.valueOf(System.currentTimeMillis());
-        String aliyunSignRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN
-                + accessUser.getUserId() + "_" + signIdentifier;
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setRootOrgId(accessUser.getRootOrgId().toString());
-        env.setUserId(accessUser.getUserId().toString());
-        env.setFileSuffix(fileSuffix);
-        YunHttpRequest aliYunHttpRequest = FileStorageUtil.getSignature(FileStorageType.ALIYUN, Constants.CAPTURE_PHOTO_UPYUN_SITEID, env, query.getFileMd5());
-        redisClient.set(aliyunSignRedisKey, aliYunHttpRequest, 60);
-        result.setAccessUrl(aliYunHttpRequest.getAccessUrl());
-        result.setFormUrl(aliYunHttpRequest.getFormUrl());
-        result.setFormParams(aliYunHttpRequest.getFormParams());
+        String signRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN + accessUser.getUserId() + "_" + signIdentifier;
+        redisClient.set(signRedisKey, result, 60);
         result.setSignIdentifier(signIdentifier);
-        return result;
-    }
 
-    @Deprecated
-    @ApiOperation(value = "批量获取抓拍照片的又拍云签名(废弃)")
-    @PostMapping("/batchGetCapturePhotoUpYunSign")
-    public BatchGetUpyunSignDomain batchGetCapturePhotoUpYunSign(@RequestBody BatchGetUpyunSignDomainQuery batchQuery) {
-        if (batchQuery.getQueryList() == null || batchQuery.getQueryList().isEmpty()) {
-            throw new StatusException("300001", "查询条件不允许为空");
-        }
-
-        List<GetUpyunSignDomain> signDomainList = new ArrayList<>();
-        for (GetUpyunSignDomainQuery query : batchQuery.getQueryList()) {
-            String fileSuffix = query.getFileSuffix();
-            if (StringUtils.isNullOrEmpty(fileSuffix)) {
-                throw new StatusException("", "文件后缀名不允许为空");
-            }
-            fileSuffix = fileSuffix.indexOf(".") == -1 ? "." + fileSuffix : fileSuffix;
-
-            GetUpyunSignDomain upyunSignDomain = new GetUpyunSignDomain();
-            User accessUser = this.getAccessUser();
-            String signIdentifier = String.valueOf(System.currentTimeMillis());
-            String upyunSignRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN
-                    + accessUser.getUserId() + "_" + signIdentifier;
-
-            UpyunPathEnvironmentInfo env = new UpyunPathEnvironmentInfo();
-            env.setRootOrgId(accessUser.getRootOrgId().toString());
-            env.setUserId(accessUser.getUserId().toString());
-            env.setFileSuffix(fileSuffix);
-            YunHttpRequest upYunHttpRequest = upyunService.buildUpYunHttpRequest(Constants.CAPTURE_PHOTO_UPYUN_SITEID, env, query.getFileMd5());
-            redisClient.set(upyunSignRedisKey, upYunHttpRequest, 60);
-            upyunSignDomain.setAccessUrl(upYunHttpRequest.getAccessUrl());
-            upyunSignDomain.setFormUrl(upYunHttpRequest.getFormUrl());
-            upyunSignDomain.setFormParams(upYunHttpRequest.getFormParams());
-            upyunSignDomain.setSignIdentifier(signIdentifier);
-
-            signDomainList.add(upyunSignDomain);
-            Util.sleep(TimeUnit.MILLISECONDS, 1);
-        }
-        BatchGetUpyunSignDomain result = new BatchGetUpyunSignDomain();
-        result.setList(signDomainList);
         return result;
     }
 

+ 15 - 25
examcloud-core-oe-student-api-provider/src/main/java/cn/com/qmth/examcloud/core/oe/student/api/controller/client/ExamProcessController.java

@@ -15,13 +15,11 @@ import cn.com.qmth.examcloud.support.examing.ExamQuestion;
 import cn.com.qmth.examcloud.support.examing.ExamRecordPaperStruct;
 import cn.com.qmth.examcloud.support.examing.ExamingSession;
 import cn.com.qmth.examcloud.support.examing.ExamingStatus;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.support.filestorage.UploadResult;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
+import cn.com.qmth.examcloud.support.fss.model.FssSignInfo;
 import cn.com.qmth.examcloud.support.handler.richtext2.RichTextConverter;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.FileStorageType;
-import cn.com.qmth.examcloud.web.filestorage.YunHttpRequest;
-import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -199,21 +197,19 @@ public class ExamProcessController extends ControllerSupport {
 
         final String fileSuffix = FileUtil.getFileSuffix(file.getOriginalFilename());
         final String newFileName = FileUtil.generateFileName();
-        //路径规则:oe/rootOrgId/yyyyMMdd/userId_fileName.fileSuffix
-        final String uploadPath = String.format("oe/%s/%s/%s_%s%s", user.getRootOrgId(), FileUtil.dateDir(), user.getUserId(), newFileName, fileSuffix);
 
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setRootOrgId(String.valueOf(user.getRootOrgId()));
-        env.setRelativePath(uploadPath);
-        YunPathInfo result = FileStorageUtil.saveFile("oe_pc_client", env, file.getBytes(), false);
+        // 路径规则:/oe/rootOrgId/yyyyMMdd/userId_fileName.fileSuffix
+        final String uploadPath = String.format("/oe/%s/%s/%s_%s%s", user.getRootOrgId(), FileUtil.dateDir(), user.getUserId(), newFileName, fileSuffix);
 
-        return new UploadResult(file.getOriginalFilename(), result.getRelativePath(), result.getUrl());
+        FssFileInfo result = FssFactory.getInstance().writeFile(uploadPath, file.getBytes(), null);
+
+        return new UploadResult(file.getOriginalFilename(), result.getFilePath(), result.getFileUrl());
     }
 
     // @Naked
-    @ApiOperation(value = "文件上传签名信息")
+    @ApiOperation(value = "获取抓拍照片文件上传签名信息")
     @PostMapping("/upload/sign")
-    public GetAliyunSignDomain getUploadSign(@RequestBody GetYunSignDomainQuery query) {
+    public FssSignInfo getUploadSign(@RequestBody GetYunSignDomainQuery query) {
         User accessUser = this.getAccessUser();
 
         if (StringUtils.isBlank(query.getFileSuffix())) {
@@ -222,21 +218,15 @@ public class ExamProcessController extends ControllerSupport {
 
         String fileSuffix = query.getFileSuffix().startsWith(".") ? query.getFileSuffix() : "." + query.getFileSuffix();
 
-        FileStoragePathEnvInfo pathEnv = new FileStoragePathEnvInfo();
-        pathEnv.setRootOrgId(String.valueOf(accessUser.getRootOrgId()));
-        pathEnv.setUserId(String.valueOf(accessUser.getUserId()));
-        pathEnv.setFileSuffix(fileSuffix);
-        YunHttpRequest uploadRequest = FileStorageUtil.getSignature(FileStorageType.ALIYUN, Constants.CAPTURE_PHOTO_UPYUN_SITEID, pathEnv, query.getFileMd5());
+        // 路径:/capture_photo/{rootOrgId}/{userId}/{timeMillis}{fileSuffix}
+        String filePath = String.format(OeConstants.CAPTURE_PHOTO_PATH, accessUser.getRootOrgId(), accessUser.getUserId(), System.currentTimeMillis(), fileSuffix);
+        FssSignInfo result = FssFactory.getInstance(false).buildSign(filePath);
 
         String signIdentifier = String.valueOf(System.currentTimeMillis());
         // String signRedisKey = CacheConstants.CACHE_OE_UPYUN_IMAGE_SIGN + accessUser.getUserId() + "_" + signIdentifier;
-        // redisClient.set(signRedisKey, uploadRequest, 60);
-
-        GetAliyunSignDomain result = new GetAliyunSignDomain();
-        result.setAccessUrl(uploadRequest.getAccessUrl());
-        result.setFormUrl(uploadRequest.getFormUrl());
-        result.setFormParams(uploadRequest.getFormParams());
+        // redisClient.set(signRedisKey, result, 60);
         result.setSignIdentifier(signIdentifier);
+
         return result;
     }
 

+ 5 - 1
examcloud-core-oe-student-base/src/main/java/cn/com/qmth/examcloud/core/oe/student/base/OeConstants.java

@@ -2,12 +2,16 @@ package cn.com.qmth.examcloud.core.oe.student.base;
 
 public interface OeConstants {
 
-
     int TIME_OUT_5_MINUTE = 60 * 5;
 
     int TIME_OUT_1_DAY = 60 * 60 * 24;
 
     int TIME_OUT_7_DAY = 60 * 60 * 24 * 7;
 
+    /**
+     * 抓拍照片路径规则
+     * /capture_photo/{rootOrgId}/{userId}/{timeMillis}{fileSuffix}
+     */
+    String CAPTURE_PHOTO_PATH = "/capture_photo/%s/%s/%s%s";
 
 }

+ 0 - 2
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/ExamControlService.java

@@ -99,8 +99,6 @@ public interface ExamControlService {
     void sendScanQrCodeToWebSocket(String clientId, Long examRecordDataId, Integer order,
                                    Long userId, Long rootOrgId) throws Exception;
 
-    UpyunSignatureInfo getUpyunSignature(GetYunSignatureReq req);
-
     /**
      * 获取二维码
      *

+ 7 - 89
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/impl/ExamCaptureServiceImpl.java

@@ -2,7 +2,6 @@ package cn.com.qmth.examcloud.core.oe.student.service.impl;
 
 import cn.com.qmth.examcloud.api.commons.enums.FaceApiProvider;
 import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.commons.helpers.JsonHttpResponseHolder;
 import cn.com.qmth.examcloud.core.oe.student.base.bean.CompareFaceSyncInfo;
 import cn.com.qmth.examcloud.core.oe.student.bean.task.CalculateFaceCheckResultInfo;
 import cn.com.qmth.examcloud.core.oe.student.bean.task.ExamCaptureQueueInfo;
@@ -26,14 +25,11 @@ import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
 import cn.com.qmth.examcloud.support.enums.ExamProperties;
 import cn.com.qmth.examcloud.support.examing.ExamRecordData;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.support.helper.ExamCacheTransferHelper;
 import cn.com.qmth.examcloud.support.helper.FaceBiopsyHelper;
-import cn.com.qmth.examcloud.web.aliyun.OssClient;
-// import cn.com.qmth.examcloud.web.facepp.FaceppClient;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
-import com.alibaba.fastjson.JSONArray;
-import com.alibaba.fastjson.JSONObject;
 import org.apache.commons.codec.binary.Base64;
 import org.apache.commons.lang3.StringUtils;
 import org.json.JSONException;
@@ -59,8 +55,6 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
 
     private static final Logger log = LoggerFactory.getLogger(ExamCaptureServiceImpl.class);
 
-    public static final String TEMP_FILE_EXP = "face_compare/";
-
     @Autowired
     private ExamCaptureRepo examCaptureRepo;
 
@@ -76,9 +70,6 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
     @Autowired
     private FaceVerifyService faceVerifyService;
 
-    @Autowired
-    private OssClient ossClient;
-
     @Autowired
     private RedisClient redisClient;
 
@@ -106,79 +97,6 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
         examCaptureQueueRepo.deleteById(examCaptureQueue.getId());
     }
 
-    // @Deprecated
-    // @Override
-    // public CompareFaceSyncInfo compareFaceSyncByFileUrl(Long studentId, String baseFaceToken, String fileUrl) {
-    //     CompareFaceSyncInfo compareFaceSyncInfo = new CompareFaceSyncInfo();
-    //     compareFaceSyncInfo.setStudentId(studentId);
-    //     JSONObject facePPResult = null;
-    //     JsonHttpResponseHolder jsonHttpResponseHolder = null;
-    //     try {
-    //         jsonHttpResponseHolder = FaceppClient.getClient().
-    //                 compareWithTokenAndImageUrl(baseFaceToken,
-    //                         FileStorageUtil.realPath(fileUrl),
-    //                         FileStorageUtil.realPathBackup(fileUrl));
-    //         facePPResult = jsonHttpResponseHolder.getRespBody();
-    //     } catch (StatusException e) {
-    //         //如果错误码是801,802,803直接结束,不重试
-    //         if (e.getCode().equals("801") || e.getCode().equals("802") || e.getCode().equals("803")) {
-    //             compareFaceSyncInfo.setIsPass(false);
-    //             compareFaceSyncInfo.setExistsSystemError(true);
-    //             compareFaceSyncInfo.setErrorMsg(e.getDesc());
-    //
-    //             log.error("[COMPARE_FACE_SYNC] face++人脸比对无法处理的图片地址,errMsg=" + e.getDesc(), e);
-    //             return compareFaceSyncInfo;
-    //         }
-    //         throw e;
-    //     } catch (Exception e) {
-    //         compareFaceSyncInfo.setIsPass(false);
-    //         compareFaceSyncInfo.setExistsSystemError(true);
-    //         compareFaceSyncInfo.setErrorMsg("系统异常");
-    //
-    //         log.error("[COMPARE_FACE_SYNC] 未处理的系统异常,errMsg=" + e.getMessage(), e);
-    //         return compareFaceSyncInfo;
-    //     }
-    //     if (facePPResult.containsKey(Constants.ERROR_MSG)) {
-    //         compareFaceSyncInfo.setFaceCompareResult(facePPResult.toString());
-    //         compareFaceSyncInfo.setIsPass(false);
-    //         String errMsg = facePPResult.getString(Constants.ERROR_MSG);
-    //         if (errMsg.contains(Constants.FACE_COMPARE_AUTHORIZATION_ERROR)) {
-    //             compareFaceSyncInfo.setExistsSystemError(true);
-    //         }
-    //         if (errMsg.contains(Constants.FACE_COMPARE_CONCURRENCY_LIMIT_EXCEEDED)) {
-    //             log.error("[FaceCompare] FacePlusPlus_QPS_CONCURRENCY_LIMITED");
-    //             compareFaceSyncInfo.setExistsSystemError(true);
-    //         }
-    //         compareFaceSyncInfo.setErrorMsg("facePP called failed : " + facePPResult.toString());
-    //         return compareFaceSyncInfo;
-    //     } else {
-    //         compareFaceSyncInfo.setFaceCompareResult(facePPResult.toString());
-    //         if (facePPResult.containsKey("confidence")) {
-    //             double confidence = facePPResult.getDouble("confidence");
-    //             JSONObject thresholdsJsonObject = facePPResult.getJSONObject("thresholds");
-    //             double le4 = thresholdsJsonObject.getDouble("1e-4");
-    //             JSONArray face2Array = facePPResult.getJSONArray("faces2");
-    //             boolean hasStranger = face2Array.size() > 1;
-    //             compareFaceSyncInfo.setIsStranger(hasStranger);//是否有陌生人
-    //             boolean isPass = confidence >= le4;
-    //             compareFaceSyncInfo.setIsPass(isPass);//是否通过
-    //             String errorMsg = null;
-    //             if (hasStranger && !isPass) {
-    //                 errorMsg = "检测过程中相片非本人,且存在多人脸";
-    //             } else if (hasStranger) {
-    //                 errorMsg = "检测过程中多人脸失败";
-    //             } else if (!isPass) {
-    //                 errorMsg = "检测过程中相片非本人";
-    //             }
-    //             compareFaceSyncInfo.setErrorMsg(errorMsg);
-    //         } else {
-    //             compareFaceSyncInfo.setIsPass(false);
-    //             compareFaceSyncInfo.setErrorMsg("未检测到人脸");
-    //         }
-    //         return compareFaceSyncInfo;
-    //     }
-    // }
-
     @Override
     public CompareFaceSyncInfo compareFaceSync(StudentCacheBean student, String fileUrl) {
         // 获取学校人脸API方案配置
@@ -208,20 +126,20 @@ public class ExamCaptureServiceImpl implements ExamCaptureService {
                     basePhoto = new ImageBase64Parm(CommonUtils.toBase64(student.getPhotoPath()));
                     log.warn("old data basePhotoUrl:{}", student.getPhotoPath());
                 } else {
-                    String basePhotoUrl = ossClient.valueOfOssFilePath(student.getPhotoPath());
-                    byte[] basePhotoBytes = ossClient.download(basePhotoUrl);
+                    String basePhotoPath = FssHelper.fixFilePath(student.getPhotoPath());
+                    byte[] basePhotoBytes = FssFactory.getInstance().readFile(basePhotoPath);
                     basePhoto = new ImageBase64Parm(Base64.encodeBase64String(basePhotoBytes));
                 }
 
-                String capturePhotoUrl = ossClient.valueOfOssFilePath(FileStorageUtil.realPath(fileUrl));
-                byte[] capturePhotoBytes = ossClient.download(capturePhotoUrl);
+                String capturePhotoPath = FssHelper.fixFilePath(fileUrl);
+                byte[] capturePhotoBytes = FssFactory.getInstance().readFile(capturePhotoPath);
                 ImageParm capturePhoto = new ImageBase64Parm(Base64.encodeBase64String(capturePhotoBytes));
 
                 faceResult = faceVerifyService.faceCompareByBaidu(basePhoto, capturePhoto, baiduExpectFaceCompareScore);
             } else {
                 ImageParm basePhoto = new ImageTokenParm(student.getFaceToken());
 
-                String capturePhotoUrl = FileStorageUtil.realPath(fileUrl);
+                String capturePhotoUrl = FssHelper.finalFileUrl(fileUrl);
                 ImageParm capturePhoto = new ImageUrlParm(capturePhotoUrl);
 
                 faceResult = faceVerifyService.faceCompareByFacePlus(basePhoto, capturePhoto);

+ 0 - 136
examcloud-core-oe-student-service/src/main/java/cn/com/qmth/examcloud/core/oe/student/service/impl/ExamControlServiceImpl.java

@@ -78,11 +78,7 @@ import com.alibaba.fastjson.JSONArray;
 import com.alibaba.fastjson.JSONObject;
 import com.fasterxml.jackson.databind.JsonNode;
 import com.google.common.base.Splitter;
-import main.java.com.upyun.Base64Coder;
-import main.java.com.upyun.UpException;
-import main.java.com.upyun.UpYunUtils;
 import org.apache.commons.collections.CollectionUtils;
-import org.apache.commons.lang.math.RandomUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.commons.lang3.time.DateUtils;
 import org.slf4j.Logger;
@@ -93,7 +89,6 @@ import org.springframework.transaction.annotation.Transactional;
 
 import java.io.UnsupportedEncodingException;
 import java.net.URLEncoder;
-import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -170,14 +165,8 @@ public class ExamControlServiceImpl implements ExamControlService {
 
     private static final String UNDERLINE = "_";
 
-    // 又拍云音频答案上传目录
-    private static final String OE_ANSWER_FILE_PATH = "oe-answer-file";
-
     private static final String SESSION_TIMEOUT = "$core.basic.sessionTimeout";
 
-    // 又拍云签名有效时间(秒)
-    private static final Integer SIGN_TIMEOUT = 60;
-
     private DefaultPaper buildPaper(ExtractConfigCacheBean extractConfig, String paperType, boolean randomPaper) {
         if (randomPaper) {
             GetRandomPaperReq req = new GetRandomPaperReq();
@@ -1175,52 +1164,6 @@ public class ExamControlServiceImpl implements ExamControlService {
         wsCloudService.sendText(sendTextReq);
     }
 
-    @Override
-    public UpyunSignatureInfo getUpyunSignature(GetYunSignatureReq req) {
-        UpyunSignatureInfo u = new UpyunSignatureInfo();
-        try {
-            ExamRecordData examRecordData = examRecordDataService.getExamRecordDataCache(req.getExamRecordDataId());
-            String md5 = req.getFileMd5();
-            Date signDate = null;
-            Date now = new Date();
-            Date expirationDate = DateUtils.addSeconds(now, SIGN_TIMEOUT);
-
-            StringBuffer filePath = new StringBuffer();
-
-            filePath.append(SEPARATOR).append(OE_ANSWER_FILE_PATH).append(SEPARATOR)
-                    .append(examRecordData.getExamStudentId()).append(SEPARATOR).append(req.getExamRecordDataId())
-                    .append(SEPARATOR).append(req.getOrder()).append(SEPARATOR)
-                    .append(examRecordData.getExamStudentId()).append(UNDERLINE).append(req.getExamRecordDataId())
-                    .append(UNDERLINE).append(req.getOrder()).append(UNDERLINE).append(System.currentTimeMillis())
-                    .append(RandomUtils.nextInt(8999) + 1000);
-
-            if (StringUtils.isNotEmpty(req.getExt())) {
-                filePath.append(UNDERLINE).append(req.getExt());
-            }
-            filePath.append(".").append(req.getFileSuffix());
-
-            long expiration = expirationDate.getTime() / 1000;
-            String bucketName = PropertyHolder.getString("$upyun.site.1.bucketName");
-            String userName = PropertyHolder.getString("$upyun.site.1.userName");
-            String password = PropertyHolder.getString("$upyun.site.1.password");
-
-            String policy = policy(bucketName, expiration, filePath.toString(), signDate, md5);
-            String sign = sign("POST", getGMTDate(signDate), bucketName, policy, userName, UpYunUtils.md5(password),
-                    md5);
-            u.setPolicy(policy);
-            u.setSignature(sign);
-            u.setFilePath(filePath.toString());
-
-            String bucketUrl = "https://v0.api.upyun.com";
-            String upyunFileUrl = PropertyHolder.getString("$upyun.site.1.domain");
-            u.setUploadUrl(UrlUtil.joinUrl(bucketUrl, bucketName));
-            u.setUpyunFileDomain(upyunFileUrl);
-        } catch (UpException e) {
-            throw new StatusException("100003", "获取又拍云签名失败");
-        }
-        return u;
-    }
-
     /**
      * 获取二维码
      *
@@ -1324,85 +1267,6 @@ public class ExamControlServiceImpl implements ExamControlService {
         return ret;
     }
 
-    /**
-     * @param bucketName //不能为空
-     * @param expiration //不能为空
-     * @param filePath   //不能为空
-     * @param date       为空时,以又怕云时间和expiration比较,不为空时以此date和expiration比较
-     * @param md5        //可以为空
-     * @return
-     */
-    private String policy(String bucketName, Long expiration, String filePath, Date date, String md5) {
-        Map<String, Object> paramMap = new HashMap<String, Object>();
-        // 不能为空
-        paramMap.put("bucket", bucketName);
-        Date expirationDate = DateUtils.addSeconds(new Date(), SIGN_TIMEOUT);
-        // 不能为空
-        paramMap.put("expiration", expirationDate.getTime() / 1000);
-        paramMap.put("save-key", filePath);
-        // 为空时,以又怕云时间和expiration比较,不为空时以此date和expiration比较
-        paramMap.put("date", date);
-        // 可以为空
-        paramMap.put("content-md5", md5);
-        String policy = UpYunUtils.getPolicy(paramMap);
-        return policy;
-    }
-
-    private String getGMTDate(Date d) {
-        if (d == null) {
-            return null;
-        }
-        SimpleDateFormat formater = new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss 'GMT'", Locale.US);
-        formater.setTimeZone(TimeZone.getTimeZone("GMT+8"));
-        return formater.format(d);
-    }
-
-    /**
-     * 必须和policy中date一致,可以都为空.GMTDate
-     *
-     * @param method
-     * @param date
-     * @param bucketName
-     * @param policy
-     * @param userName
-     * @param password
-     * @param md5
-     * @return
-     * @throws UpException
-     */
-    private String sign(String method, String date, String bucketName, String policy, String userName, String password,
-                        String md5) throws UpException {
-
-        StringBuilder sb = new StringBuilder();
-        String sp = "&";
-        sb.append(method);
-        sb.append(sp);
-        sb.append(SEPARATOR + bucketName);
-        if (date != null) {
-            sb.append(sp);
-            sb.append(date);
-        }
-        sb.append(sp);
-        sb.append(policy);
-        if (md5 != null && md5.length() > 0) {
-            sb.append(sp);
-            sb.append(md5);
-        }
-        String raw = sb.toString().trim();
-        byte[] hmac = null;
-        try {
-            hmac = UpYunUtils.calculateRFC2104HMACRaw(password, raw);
-        } catch (Exception e) {
-            throw new UpException("calculate SHA1 wrong.");
-        }
-
-        if (hmac != null) {
-            return "UPYUN " + userName + ":" + Base64Coder.encodeLines(hmac).trim();
-        }
-
-        return null;
-    }
-
     /**
      * 检查并返回考试 开考条件 1.enable为true 2.开始时间和结束时间判断 3.examLimit为null或false
      * 4.剩余考试次数>0

+ 0 - 4
examcloud-core-oe-student-starter/src/main/java/cn/com/qmth/examcloud/core/oe/student/starter/OEStudentApp.java

@@ -1,7 +1,6 @@
 package cn.com.qmth.examcloud.core.oe.student.starter;
 
 import cn.com.qmth.examcloud.core.oe.student.dao.UniqueRuleHolder;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.web.jpa.DataIntegrityViolationTransverter;
 import org.springframework.boot.SpringApplication;
 import org.springframework.boot.autoconfigure.SpringBootApplication;
@@ -43,9 +42,6 @@ public class OEStudentApp {
     public static void main(String[] args) {
         // AppBootstrap.run(OEStudentApp.class, args);
         SpringApplication.run(OEStudentApp.class, args);
-
-        FileStorageUtil.initYunSite();
-        FileStorageUtil.initYunClient();
     }
 
     @Bean(name = "multipartResolver")