瀏覽代碼

upgrade fss api...

deason 11 月之前
父節點
當前提交
9a8c2c2bda
共有 13 個文件被更改,包括 212 次插入185 次删除
  1. 36 80
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java
  2. 2 5
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java
  3. 4 11
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java
  4. 12 17
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SysNoticeController.java
  5. 12 9
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SystemPropertyController.java
  6. 4 2
      examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/StudentCloudServiceProvider.java
  7. 59 0
      examcloud-core-basic-base/src/main/java/cn/com/qmth/examcloud/core/basic/base/constants/FileConstants.java
  8. 51 0
      examcloud-core-basic-base/src/main/java/cn/com/qmth/examcloud/core/basic/base/util/PhotoPathHelper.java
  9. 4 10
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/cache/StudentCache.java
  10. 8 13
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/LoginRuleServiceImpl.java
  11. 16 25
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/ResourceServiceImpl.java
  12. 4 10
      examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/StudentServiceImpl.java
  13. 0 3
      examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/CoreBasicApp.java

+ 36 - 80
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/OrgController.java

@@ -15,6 +15,7 @@ import cn.com.qmth.examcloud.commons.util.PathUtil;
 import cn.com.qmth.examcloud.commons.util.RegExpUtil;
 import cn.com.qmth.examcloud.core.basic.api.controller.bean.OrgDomain;
 import cn.com.qmth.examcloud.core.basic.api.controller.bean.SaveOrgPropertiesDomain;
+import cn.com.qmth.examcloud.core.basic.base.constants.FileConstants;
 import cn.com.qmth.examcloud.core.basic.base.constants.SystemProps;
 import cn.com.qmth.examcloud.core.basic.dao.OrgPropertyRepo;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
@@ -36,12 +37,11 @@ import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.OrgCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.OrgPropertyCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
 import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
 import cn.com.qmth.examcloud.task.api.request.SyncOrgReq;
 import cn.com.qmth.examcloud.web.config.SystemProperties;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.jpa.PageUtils;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
@@ -689,7 +689,7 @@ public class OrgController extends ControllerSupport {
         return properties;
     }
 
-    private List<String> uploadOrgProperties2Upyun(Long orgId, String propertyGroupId) {
+    private List<String> uploadOrgProperties(Long orgId, String propertyGroupId) {
         Map<String, String> properties = getOrgPropertiesByGroup(orgId, propertyGroupId);
 
         OrgCacheBean org = CacheHelper.getOrg(orgId);
@@ -720,49 +720,26 @@ public class OrgController extends ControllerSupport {
         try {
             FileUtils.write(file, prettyJson, "UTF-8");
 
-            //			PutFileReq req = new PutFileReq();
-            //			List<FormFilePart> formFilePartList = new ArrayList<FormFilePart>();
-            //			FormFilePart part = new FormFilePart("file", orgId + fileSuffix, file);
-            //			formFilePartList.add(part);
-            //
-            //			req.setFormFilePartList(formFilePartList);
-            //
-            //			req.setFileSuffix(fileSuffix);
-            //			req.setRootOrgId(orgEntity.getId());
-            //			req.setRootOrgDomain(orgEntity.getDomainName());
-            //			req.setExt1(propertyGroupId);
-            //
-            //			PutFileResp putFileResp = null;
-            //
-            //			req.setSiteId("orgPropertiesByOrgId");
-            //			putFileResp = upyunCloudService.putFile(req);
-            //			urlList.add(putFileResp.getUrl());
-            //
-            //			req.setSiteId("orgPropertiesByOrgDomain");
-            //			putFileResp = upyunCloudService.putFile(req);
-            //			urlList.add(putFileResp.getUrl());
-
-            //通用存储
-            YunPathInfo pi = null;
-            FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            env.setFileSuffix(fileSuffix);
-            env.setRootOrgId(orgEntity.getId().toString());
-            env.setRootOrgDomain(orgEntity.getDomainName());
-            env.setExt1(propertyGroupId);
-            pi = FileStorageUtil.saveFile("orgPropertiesByOrgId", env, file, null, 0L);
-
-            urlList.add(pi.getUrl());
-            pi = FileStorageUtil.saveFile("orgPropertiesByOrgDomain", env, file, null, 0L);
-            urlList.add(pi.getUrl());
+            // 示例:/org_properties/byOrgId/0/studentClientConfig.json
+            String filePath1 = String.format(FileConstants.ORG_PROPERTIES_BY_ORG_ID, orgId, propertyGroupId + fileSuffix);
+            FssFileInfo result1 = FssFactory.getInstance().writeFile(filePath1, file, null);
+            urlList.add(result1.getFileUrl());
 
-            return urlList;
+            // 示例:/org_properties/byOrgDomain/0/studentClientConfig.json
+            String filePath2 = String.format(FileConstants.ORG_PROPERTIES_BY_ORG_DOMAIN, orgEntity.getDomainName(), propertyGroupId + fileSuffix);
+            FssFileInfo result2 = FssFactory.getInstance().writeFile(filePath2, file, null);
+            urlList.add(result2.getFileUrl());
+
+            // 刷新CDN缓存
+            FssFactory.getInstance().refreshFile(result1.getFileUrl());
+            FssFactory.getInstance().refreshFile(result2.getFileUrl());
 
+            return urlList;
         } catch (IOException e) {
             throw new ExamCloudRuntimeException(e);
         } finally {
             FileUtils.deleteQuietly(file);
         }
-
     }
 
     public Map<String, String> getOrgPropertiesByGroup(Long orgId, String propertyGroupId) {
@@ -1154,8 +1131,8 @@ public class OrgController extends ControllerSupport {
                 String redisKey = CacheConstants.CACHE_B_ORG_PROP_LIST + orgId + ":" + propertyGroupId;
                 redisClient.delete(redisKey);
 
-                // 上传upyun
-                uploadOrgProperties2Upyun(orgId, propertyGroupId);
+                // 上传
+                uploadOrgProperties(orgId, propertyGroupId);
             }
         }
 
@@ -1369,24 +1346,10 @@ public class OrgController extends ControllerSupport {
 
         FileUtils.copyFile(storeLocation, new File(path));
 
-        //		PutFileReq req = new PutFileReq();
-        //		List<FormFilePart> formFilePartList = new ArrayList<FormFilePart>();
-        //		FormFilePart part = new FormFilePart("file", orgId + fileSuffix, storeLocation);
-        //		formFilePartList.add(part);
-        //
-        //		req.setFormFilePartList(formFilePartList);
-        //		req.setSiteId("orgLogo");
-        //		req.setFileSuffix(fileSuffix);
-        //		req.setRootOrgId(orgEntity.getRootId());
-        //		PutFileResp putFileResp = upyunCloudService.putFile(req);
-        //		String url = putFileResp.getUrl();
-
-        //通用存储
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setFileSuffix(fileSuffix);
-        env.setRootOrgId(orgEntity.getRootId().toString());
-        YunPathInfo pi = FileStorageUtil.saveFile("orgLogo", env, storeLocation, null, LOG_FILE_CACHE_AGE);
-        String url = pi.getUrl();
+        // 示例:/org_logo/0/xxx.png
+        String filePath = String.format(FileConstants.ORG_LOGO, orgId, System.currentTimeMillis(), fileSuffix);
+        FssFileInfo result = FssFactory.getInstance().writeFile(filePath, storeLocation, null);
+        String url = result.getFileUrl();
 
         OrgPropertyEntity logoFileUrlEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId,
                 logoFileUrl.getId());
@@ -1434,7 +1397,7 @@ public class OrgController extends ControllerSupport {
         File storeLocation = fileItem.getStoreLocation();
         String name = file.getOriginalFilename();
 
-        if (1 * 1024 * 1024 < storeLocation.length()) {
+        if (1024 * 1024 < storeLocation.length()) {
             throw new StatusException("140082", "文件过大");
         }
 
@@ -1453,13 +1416,10 @@ public class OrgController extends ControllerSupport {
         DynamicEnumManager manager = OrgProperty.getDynamicEnumManager();
         DynamicEnum logoFileUrl = manager.getByName("STUDENT_CLIENT_BG_PICTURE_URL");
 
-
-        //通用存储
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setFileSuffix(fileSuffix);
-        env.setRootOrgId(orgEntity.getRootId().toString());
-        YunPathInfo pi = FileStorageUtil.saveFile("client_bg_picture", env, storeLocation, null, LOG_FILE_CACHE_AGE);
-        String url = pi.getUrl();
+        // 示例:/client_bg_picture/0/xxx.png
+        String filePath = String.format(FileConstants.CLIENT_BG_PICTURE, orgId, System.currentTimeMillis(), fileSuffix);
+        FssFileInfo result = FssFactory.getInstance().writeFile(filePath, storeLocation, null);
+        String url = result.getFileUrl();
 
         OrgPropertyEntity logoFileUrlEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId,
                 logoFileUrl.getId());
@@ -1502,12 +1462,10 @@ public class OrgController extends ControllerSupport {
             throw new StatusException("101001", "文件格式错误");
         }
 
-        //通用存储
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setFileSuffix(fileSuffix);
-        env.setRootOrgId(orgEntity.getRootId().toString());
-        YunPathInfo pi = FileStorageUtil.saveFile("orgAnswers", env, storeLocation, null);
-        String url = pi.getUrl();
+        // 示例:/org_answers/0/xxx.zip
+        String filePath = String.format(FileConstants.ORG_ANSWER_TEMPLATE, orgId, System.currentTimeMillis(), fileSuffix);
+        FssFileInfo result = FssFactory.getInstance().writeFile(filePath, storeLocation, null);
+        String url = result.getFileUrl();
 
         User accessUser = getAccessUser();
         ReportsUtil.report(new AdminOperateReport(accessUser.getRootOrgId(), accessUser.getUserId(), AdminOperateType.TYPE4.getDesc(), null));
@@ -1635,12 +1593,10 @@ public class OrgController extends ControllerSupport {
 
         FileUtils.copyFile(storeLocation, new File(path));
 
-        //通用存储
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setFileSuffix(fileSuffix);
-        env.setRootOrgId(orgEntity.getRootId().toString());
-        YunPathInfo pi = FileStorageUtil.saveFile("orgLogo", env, storeLocation, null, LOG_FILE_CACHE_AGE);
-        String url = pi.getUrl();
+        // 示例:/org_logo/0/xxx.png
+        String filePath = String.format(FileConstants.ORG_LOGO, orgId, System.currentTimeMillis(), fileSuffix);
+        FssFileInfo result = FssFactory.getInstance().writeFile(filePath, storeLocation, null);
+        String url = result.getFileUrl();
 
         OrgPropertyEntity logoFileUrlEntity = orgPropertyRepo.findByOrgIdAndKeyId(orgId,
                 logoFileUrl.getId());

+ 2 - 5
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/ResourceController.java

@@ -8,7 +8,7 @@ import cn.com.qmth.examcloud.core.basic.dao.ResourceRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
 import cn.com.qmth.examcloud.core.basic.service.ResourceService;
 import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import com.google.common.collect.Lists;
 import io.swagger.annotations.Api;
@@ -90,14 +90,11 @@ public class ResourceController extends ControllerSupport {
 
         List<ResourceDomain> resourceDomainList = Lists.newArrayList();
 
-//		String upyunFileUrl = PropertyHolder.getString("$upyun.site.1.domain");
         while (iterator.hasNext()) {
             ResourceEntity next = iterator.next();
             ResourceDomain bean = new ResourceDomain();
             BeanUtils.copyProperties(next, bean);
-//			bean.setFileUrl(upyunFileUrl + bean.getFilePath());
-            //通用存储
-            bean.setFileUrl(FileStorageUtil.realPath(bean.getFileTreatyPath()));
+            bean.setFileUrl(FssHelper.finalFileUrl(bean.getFileTreatyPath()));
             resourceDomainList.add(bean);
         }
         PageInfo<ResourceDomain> ret = new PageInfo<ResourceDomain>();

+ 4 - 11
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/StudentController.java

@@ -12,6 +12,7 @@ import cn.com.qmth.examcloud.commons.util.ByteUtil;
 import cn.com.qmth.examcloud.commons.util.SHA256;
 import cn.com.qmth.examcloud.core.basic.api.controller.bean.StudentDomain;
 import cn.com.qmth.examcloud.core.basic.base.constants.BasicConsts;
+import cn.com.qmth.examcloud.core.basic.base.util.PhotoPathHelper;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentCodeRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentRepo;
@@ -29,7 +30,7 @@ import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
 import cn.com.qmth.examcloud.support.cache.CacheHelper;
 import cn.com.qmth.examcloud.support.cache.bean.OrgCacheBean;
 import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.support.helper.IdentityNumberHelper;
 import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
 import cn.com.qmth.examcloud.web.config.SystemProperties;
@@ -227,11 +228,6 @@ public class StudentController extends ControllerSupport {
         Iterator<StudentEntity> iterator = studentList.iterator();
         List<StudentDomain> studentDomainList = Lists.newArrayList();
 
-        //		String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
-        //		if (StringUtils.isBlank(upyunDomain)) {
-        //			throw new StatusException("560111", "property[$upyun.site.1.domain] is not configured");
-        //		}
-
         while (iterator.hasNext()) {
             StudentEntity next = iterator.next();
             StudentDomain bean = new StudentDomain();
@@ -253,11 +249,8 @@ public class StudentController extends ControllerSupport {
             bean.setIdentityNumber(next.getIdentityNumber());
             bean.setPrivateIdentityNumber(IdentityNumberHelper.conceal(next.getRootOrgId(), next.getIdentityNumber()));
             if (StringUtils.isNotBlank(next.getPhotoPath())) {
-                //				bean.setPhotoPath(
-                //						UrlUtil.joinUrl(upyunDomain, "student_base_photo", next.getPhotoPath()));
-                //通用存储
-                bean.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo",
-                        next.getPhotoPath())));
+                String photoPath = PhotoPathHelper.fixPhotoPath(next.getPhotoPath());
+                bean.setPhotoPath(FssHelper.finalFileUrl(photoPath));
             }
             bean.setPhoneNumber(next.getPhoneNumber());
             bean.setSecurityPhone(next.getSecurityPhone());

+ 12 - 17
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SysNoticeController.java

@@ -6,12 +6,12 @@ import cn.com.qmth.examcloud.commons.util.DateUtil;
 import cn.com.qmth.examcloud.commons.util.JsonUtil;
 import cn.com.qmth.examcloud.commons.util.PathUtil;
 import cn.com.qmth.examcloud.core.basic.api.controller.bean.SysNoticeDomain;
+import cn.com.qmth.examcloud.core.basic.base.constants.FileConstants;
 import cn.com.qmth.examcloud.core.basic.dao.SysNoticeRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.SysNoticeEntity;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
 import cn.com.qmth.examcloud.web.config.SystemProperties;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import com.mysql.cj.util.StringUtils;
@@ -128,30 +128,25 @@ public class SysNoticeController extends ControllerSupport {
         String prettyJson = JsonUtil.toPrettyJson(resultNotice);
 
         String fileSuffix = ".json";
-        String filePath = systemConfig.getTempDataDir() + File.separator + "notice"
+        String localFilePath = systemConfig.getTempDataDir() + File.separator + "notice"
                 + File.separator + resultNotice.getRootOrgId() + fileSuffix;
-        filePath = PathUtil.getCanonicalPath(filePath);
-        File file = new File(filePath);
+        localFilePath = PathUtil.getCanonicalPath(localFilePath);
+        File file = new File(localFilePath);
 
         try {
             FileUtils.write(file, prettyJson, "UTF-8");
 
-            //通用存储
-            YunPathInfo pi = null;
-            FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            env.setFileSuffix(fileSuffix);
-            String strRootOrgId = -1 == resultNotice.getRootOrgId()
-                    ? "all"
-                    : String.valueOf(resultNotice.getRootOrgId());
-            env.setRootOrgId(strRootOrgId);
-            pi = FileStorageUtil.saveFile("sysNotice", env, file, null);
-
-            return pi.getUrl();//返回通知保存的地址
+            // 示例:/sys_notice/org_all.json
+            String strRootOrgId = (resultNotice.getRootOrgId() == -1) ? "all" : String.valueOf(resultNotice.getRootOrgId());
+            String filePath = String.format(FileConstants.SYS_NOTICE, strRootOrgId, fileSuffix);
+            FssFileInfo result = FssFactory.getInstance().writeFile(filePath, file, null);
 
+            return result.getFileUrl();//返回通知保存的地址
         } catch (IOException e) {
             throw new ExamCloudRuntimeException(e);
         } finally {
             FileUtils.deleteQuietly(file);
         }
     }
+
 }

+ 12 - 9
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/controller/SystemPropertyController.java

@@ -11,6 +11,9 @@ import java.util.stream.Stream;
 import javax.persistence.criteria.Predicate;
 import javax.validation.Valid;
 
+import cn.com.qmth.examcloud.core.basic.base.constants.FileConstants;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.logging.log4j.core.config.plugins.validation.constraints.Required;
@@ -41,9 +44,7 @@ import cn.com.qmth.examcloud.core.basic.dao.entity.SystemPropertyEntity;
 import cn.com.qmth.examcloud.core.basic.service.SystemPropertyService;
 import cn.com.qmth.examcloud.core.basic.service.bean.SystemPropertyInfo;
 import cn.com.qmth.examcloud.core.basic.service.cache.SystemPropertyCache;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.web.config.SystemProperties;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import io.swagger.annotations.Api;
@@ -79,11 +80,9 @@ public class SystemPropertyController extends ControllerSupport {
     		dir.mkdirs();
 			File file = new File(dir.getAbsoluteFile()+"/software.json");
 			file.createNewFile();
-			try {
-				FileStorageUtil.saveUrlAs(FileStorageUtil.realPath("aliyun-1://oe_client/software.json"), file);
-			} catch (Exception e) {
-				return "";
-			}
+
+            FssFactory.getInstance().readFile(FileConstants.OE_CLIENT_BLACK_LIST, file);
+
 			String content=FileUtils.readFileToString(file, "UTF-8");
 			if(StringUtils.isBlank(content)) {
 				return "";
@@ -116,8 +115,12 @@ public class SystemPropertyController extends ControllerSupport {
 				String ret=sb.toString()+UUID.randomUUID().toUpperCase();
 				FileUtils.write(file, ret, "UTF-8");
 			}
-			FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            FileStorageUtil.saveFile("blacklist", env, file, null,0L);
+
+            // 路径:/oe_client/software.json
+            FssFileInfo result = FssFactory.getInstance().writeFile(FileConstants.OE_CLIENT_BLACK_LIST, file, null);
+
+            // 刷新CDN缓存
+            FssFactory.getInstance().refreshFile(result.getFileUrl());
 		} catch (IOException e) {
 			throw new StatusException("500","保存失败",e);
 		}finally {

+ 4 - 2
examcloud-core-basic-api-provider/src/main/java/cn/com/qmth/examcloud/core/basic/api/provider/StudentCloudServiceProvider.java

@@ -7,6 +7,7 @@ import cn.com.qmth.examcloud.core.basic.api.StudentCloudService;
 import cn.com.qmth.examcloud.core.basic.api.bean.StudentBean;
 import cn.com.qmth.examcloud.core.basic.api.request.*;
 import cn.com.qmth.examcloud.core.basic.api.response.*;
+import cn.com.qmth.examcloud.core.basic.base.util.PhotoPathHelper;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentRepo;
 import cn.com.qmth.examcloud.core.basic.dao.UserRepo;
@@ -15,7 +16,7 @@ import cn.com.qmth.examcloud.core.basic.dao.entity.StudentEntity;
 import cn.com.qmth.examcloud.core.basic.service.StudentService;
 import cn.com.qmth.examcloud.core.basic.service.bean.StudentInfo;
 import cn.com.qmth.examcloud.core.basic.service.cache.StudentCache;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import cn.com.qmth.examcloud.web.support.ControllerSupport;
 import com.google.common.collect.Lists;
@@ -303,7 +304,8 @@ public class StudentCloudServiceProvider extends ControllerSupport implements St
             StudentBean studentBean = toStudentBean(entry.getValue());
 
             if (StringUtils.isNotBlank(studentBean.getPhotoPath())) {
-                studentBean.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", studentBean.getPhotoPath())));
+                String photoPath = PhotoPathHelper.fixPhotoPath(studentBean.getPhotoPath());
+                studentBean.setPhotoPath(FssHelper.finalFileUrl(photoPath));
             }
 
             studentMaps.put(entry.getKey(), studentBean);

+ 59 - 0
examcloud-core-basic-base/src/main/java/cn/com/qmth/examcloud/core/basic/base/constants/FileConstants.java

@@ -0,0 +1,59 @@
+package cn.com.qmth.examcloud.core.basic.base.constants;
+
+/**
+ * 文件存储相关常量
+ */
+public interface FileConstants {
+
+    /**
+     * 文件路径分隔符
+     */
+    String FILE_PATH_SEPARATOR = "/";
+
+    /**
+     * 顶级机构配置路径(按机构ID)
+     * /org_properties/byOrgId/{rootOrgId}/{fileName}
+     */
+    String ORG_PROPERTIES_BY_ORG_ID = "/org_properties/byOrgId/%s/%s";
+
+    /**
+     * 顶级机构配置路径(按机构域名)
+     * /org_properties/byOrgDomain/{rootOrgDomain}/{fileName}
+     */
+    String ORG_PROPERTIES_BY_ORG_DOMAIN = "/org_properties/byOrgDomain/%s/%s";
+
+    /**
+     * 顶级机构属性-登录规则配置路径
+     */
+    String ORG_PROPERTIES_LOGIN_RULES = "/org_properties/geetestConfig.json";
+
+    /**
+     * 顶级机构答题纸路径
+     * /org_answers/${rootOrgId}/${timeMillis}${fileSuffix}
+     */
+    String ORG_ANSWER_TEMPLATE = "/org_answers/%s/%s%s";
+
+    /**
+     * 学校LOGO路径
+     * /org_logo/{rootOrgId}/{timeMillis}{fileSuffix}
+     */
+    String ORG_LOGO = "/org_logo/%s/%s%s";
+
+    /**
+     * 考生端登录界面图片路径
+     * /client_bg_picture/{rootOrgId}/{timeMillis}{fileSuffix}
+     */
+    String CLIENT_BG_PICTURE = "/client_bg_picture/%s/%s%s";
+
+    /**
+     * 软件黑名单配置路径
+     */
+    String OE_CLIENT_BLACK_LIST = "/oe_client/software.json";
+
+    /**
+     * 系统通知配置路径
+     * /sys_notice/org_${rootOrgId_or_all}${fileSuffix}
+     */
+    String SYS_NOTICE = "/sys_notice/org_%s%s";
+
+}

+ 51 - 0
examcloud-core-basic-base/src/main/java/cn/com/qmth/examcloud/core/basic/base/util/PhotoPathHelper.java

@@ -0,0 +1,51 @@
+package cn.com.qmth.examcloud.core.basic.base.util;
+
+import org.apache.commons.lang3.StringUtils;
+
+public class PhotoPathHelper {
+
+    /**
+     * 修正学生照片路径(兼容旧数据)
+     * 路径规则:/student_base_photo/{rootOrgId}/{userId}/{timeMillis}{fileSuffix}
+     *
+     * @param photoPath 文件存储路径,格式示例:
+     *                  https://ecs-static-upyun.qmth.com.cn/student_base_photo/0/1/1709710625950.png 又拍云路径(旧数据)
+     *                  https://ecs-static.qmth.com.cn/student_base_photo/0/1/1709710625950.png
+     *                  upyun-1://student_base_photo/0/1/1709710625950.png
+     *                  aliyun-1://student_base_photo/0/1/1709710625950.png
+     *                  aliyun-2://student_base_photo/0/1/1709710625950.png
+     *                  /student_base_photo/0/1/1709710625950.png
+     *                  student_base_photo/0/1/1709710625950.png
+     *                  /0/1/1709710625950.png 缺少根目录(旧数据)
+     *                  0/1/1709710625950.png 缺少根目录(旧数据)
+     * @return 标准规则的学生照片路径
+     */
+    public static String fixPhotoPath(String photoPath) {
+        if (StringUtils.isEmpty(photoPath)) {
+            return "";
+        }
+
+        if (photoPath.toLowerCase().startsWith("http")) {
+            return photoPath;
+        }
+
+        photoPath = photoPath.replace("upyun-1://", "").replace("aliyun-1://", "").replace("aliyun-2://", "");
+
+        if (photoPath.contains("student_base_photo")) {
+            if (photoPath.startsWith("/")) {
+                return photoPath;
+            }
+            return "/" + photoPath;
+        } else {
+            if (photoPath.startsWith("/")) {
+                return "/student_base_photo" + photoPath;
+            }
+            return "/student_base_photo/" + photoPath;
+        }
+    }
+
+    /*public static void main(String[] args) {
+        System.out.println(fixPhotoPath("0/1/1709710625950.png"));
+    }*/
+
+}

+ 4 - 10
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/cache/StudentCache.java

@@ -1,5 +1,6 @@
 package cn.com.qmth.examcloud.core.basic.service.cache;
 
+import cn.com.qmth.examcloud.core.basic.base.util.PhotoPathHelper;
 import cn.com.qmth.examcloud.core.basic.dao.StudentCodeRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentFaceRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentRepo;
@@ -8,7 +9,7 @@ import cn.com.qmth.examcloud.core.basic.dao.entity.StudentEntity;
 import cn.com.qmth.examcloud.core.basic.dao.entity.StudentFaceEntity;
 import cn.com.qmth.examcloud.support.CacheConstants;
 import cn.com.qmth.examcloud.support.cache.bean.StudentCacheBean;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.web.cache.RandomObjectRedisCache;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
 import com.google.common.collect.Lists;
@@ -49,15 +50,8 @@ public class StudentCache extends RandomObjectRedisCache<StudentCacheBean> {
         b.setSecurityPhone(s.getSecurityPhone());
 
         if (StringUtils.isNotBlank(s.getPhotoPath())) {
-            //			String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
-            //			if (StringUtils.isBlank(upyunDomain)) {
-            //				throw new StatusException("560111",
-            //						"property[$upyun.site.1.domain] is not configured");
-            //			}
-            //			String path = UrlUtil.joinUrl(upyunDomain, "student_base_photo", s.getPhotoPath());
-            //			b.setPhotoPath(path);
-            //通用存储
-            b.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", s.getPhotoPath())));
+            String photoPath = PhotoPathHelper.fixPhotoPath(s.getPhotoPath());
+            b.setPhotoPath(FssHelper.finalFileUrl(photoPath));
         }
 
         List<StudentCodeEntity> studentCodeEntityList = studentCodeRepo.findByStudentId(s.getId());

+ 8 - 13
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/LoginRuleServiceImpl.java

@@ -7,6 +7,7 @@ package cn.com.qmth.examcloud.core.basic.service.impl;
 
 import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.JsonUtil;
+import cn.com.qmth.examcloud.core.basic.base.constants.FileConstants;
 import cn.com.qmth.examcloud.core.basic.dao.LoginRuleRepo;
 import cn.com.qmth.examcloud.core.basic.dao.entity.LoginRuleEntity;
 import cn.com.qmth.examcloud.core.basic.dao.enums.LoginRuleType;
@@ -16,9 +17,8 @@ import cn.com.qmth.examcloud.core.basic.service.bean.LoginRuleForm;
 import cn.com.qmth.examcloud.core.basic.service.bean.LoginRuleInfo;
 import cn.com.qmth.examcloud.core.basic.service.bean.LoginRuleQuery;
 import cn.com.qmth.examcloud.support.CacheConstants;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
 import cn.com.qmth.examcloud.web.redis.RedisClient;
 import org.apache.commons.collections.CollectionUtils;
 import org.apache.commons.collections.MapUtils;
@@ -38,11 +38,6 @@ public class LoginRuleServiceImpl implements LoginRuleService {
 
     private static final Logger LOG = LoggerFactory.getLogger(LoginRuleServiceImpl.class);
 
-    /**
-     * ../resources/aliyun.xml siteId
-     */
-    private static final String LOGIN_RULE_SITE_ID = "orgProperties";
-
     private static final long TOP_ID = -1L;
 
     @Autowired
@@ -188,11 +183,11 @@ public class LoginRuleServiceImpl implements LoginRuleService {
 
     private void uploadJsonFile(String json) {
         try {
-            // 路径:../org_properties/geetestConfig.json
-            FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-            env.setExt1("geetestConfig");
-            YunPathInfo oss = FileStorageUtil.saveFile(LOGIN_RULE_SITE_ID, env, json.getBytes(), true);
-            LOG.debug(oss.getRelativePath());
+            // 路径:/org_properties/geetestConfig.json
+            FssFileInfo result = FssFactory.getInstance().writeFile(FileConstants.ORG_PROPERTIES_LOGIN_RULES, json.getBytes(), null);
+
+            // 刷新CDN缓存
+            FssFactory.getInstance().refreshFile(result.getFileUrl());
         } catch (Exception e) {
             LOG.error(e.getMessage(), e);
         }

+ 16 - 25
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/ResourceServiceImpl.java

@@ -1,23 +1,21 @@
 package cn.com.qmth.examcloud.core.basic.service.impl;
 
-import java.io.File;
-import java.util.Date;
-import java.util.Optional;
-
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.core.basic.dao.ResourceRepo;
+import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
+import cn.com.qmth.examcloud.core.basic.service.ResourceService;
+import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
+import cn.com.qmth.examcloud.support.fss.FssFactory;
+import cn.com.qmth.examcloud.support.fss.model.FssFileInfo;
 import org.apache.commons.fileupload.disk.DiskFileItem;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
 import org.springframework.web.multipart.MultipartFile;
 import org.springframework.web.multipart.commons.CommonsMultipartFile;
 
-import cn.com.qmth.examcloud.commons.exception.StatusException;
-import cn.com.qmth.examcloud.core.basic.dao.ResourceRepo;
-import cn.com.qmth.examcloud.core.basic.dao.entity.ResourceEntity;
-import cn.com.qmth.examcloud.core.basic.service.ResourceService;
-import cn.com.qmth.examcloud.core.basic.service.bean.ResourceInfo;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
-import cn.com.qmth.examcloud.web.filestorage.FileStoragePathEnvInfo;
-import cn.com.qmth.examcloud.web.filestorage.YunPathInfo;
+import java.io.File;
+import java.util.Date;
+import java.util.Optional;
 
 @Service
 public class ResourceServiceImpl implements ResourceService {
@@ -29,9 +27,6 @@ public class ResourceServiceImpl implements ResourceService {
     @Autowired
     ResourceRepo resourceRepo;
 
-    // @Autowired
-    // UpyunCloudService upyunCloudService;
-
     @Override
     public void addDir(ResourceInfo info) {
 
@@ -67,7 +62,6 @@ public class ResourceServiceImpl implements ResourceService {
         String suffix = fileName.substring(fileName.lastIndexOf(".") + 1, fileName.length());
         e.setSuffix(suffix);
 
-
         if (parentId == null) {
             e.setParentId(null);
             e.setFilePath(FILE_ROOT_PATH + FILE_PATH_SEPARATE + rootOrgId + FILE_PATH_SEPARATE + fileName);
@@ -81,18 +75,15 @@ public class ResourceServiceImpl implements ResourceService {
                 throw new StatusException("100020", "上级目录不存在");
             }
         }
-        
+
         CommonsMultipartFile cf = (CommonsMultipartFile) dataFile;
         DiskFileItem fi = (DiskFileItem) cf.getFileItem();
 
         File f = fi.getStoreLocation();
-        // 通用存储
-        FileStoragePathEnvInfo env = new FileStoragePathEnvInfo();
-        env.setRootOrgId(rootOrgId.toString());
-        env.setRelativePath(e.getFilePath());
-        YunPathInfo pi=FileStorageUtil.saveFile("resource", env, f, null);
-        e.setFileTreatyPath(pi.getRelativePath());
-        
+
+        FssFileInfo result = FssFactory.getInstance().writeFile(e.getFilePath(), f, null);
+        e.setFileTreatyPath(result.getFilePath());
+
         ResourceEntity olde = resourceRepo.findByRootOrgIdAndFilePath(rootOrgId, e.getFilePath());
         if (olde != null) {
             olde.setUpdateTime(new Date());
@@ -100,6 +91,6 @@ public class ResourceServiceImpl implements ResourceService {
         } else {
             resourceRepo.save(e);
         }
-
     }
+
 }

+ 4 - 10
examcloud-core-basic-service/src/main/java/cn/com/qmth/examcloud/core/basic/service/impl/StudentServiceImpl.java

@@ -4,6 +4,7 @@ import cn.com.qmth.examcloud.commons.exception.StatusException;
 import cn.com.qmth.examcloud.commons.util.ByteUtil;
 import cn.com.qmth.examcloud.commons.util.SHA256;
 import cn.com.qmth.examcloud.core.basic.base.constants.BasicConsts;
+import cn.com.qmth.examcloud.core.basic.base.util.PhotoPathHelper;
 import cn.com.qmth.examcloud.core.basic.dao.OrgRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentCodeRepo;
 import cn.com.qmth.examcloud.core.basic.dao.StudentRepo;
@@ -16,7 +17,7 @@ import cn.com.qmth.examcloud.core.basic.service.UserService;
 import cn.com.qmth.examcloud.core.basic.service.bean.StudentInfo;
 import cn.com.qmth.examcloud.core.basic.service.cache.OrgCache;
 import cn.com.qmth.examcloud.core.basic.service.cache.StudentCache;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
+import cn.com.qmth.examcloud.support.fss.FssHelper;
 import cn.com.qmth.examcloud.task.api.DataSyncCloudService;
 import cn.com.qmth.examcloud.task.api.request.SyncStudentReq;
 import cn.com.qmth.examcloud.web.helpers.GlobalHelper;
@@ -327,15 +328,8 @@ public class StudentServiceImpl implements StudentService {
         info.setPhoneNumber(s.getPhoneNumber());
 
         if (StringUtils.isNotBlank(s.getPhotoPath())) {
-            //			String upyunDomain = PropertyHolder.getString("$upyun.site.1.domain");
-            //			if (StringUtils.isBlank(upyunDomain)) {
-            //				throw new StatusException("560111",
-            //						"property[$upyun.site.1.domain] is not configured");
-            //			}
-            //			String path = UrlUtil.joinUrl(upyunDomain, "student_base_photo", s.getPhotoPath());
-            //			info.setPhotoPath(path);
-            //通用存储
-            info.setPhotoPath(FileStorageUtil.realPath(FileStorageUtil.getIntactPath("student_base_photo", s.getPhotoPath())));
+            String photoPath = PhotoPathHelper.fixPhotoPath(s.getPhotoPath());
+            info.setPhotoPath(FssHelper.finalFileUrl(photoPath));
         }
 
         info.setRemark(s.getRemark());

+ 0 - 3
examcloud-core-basic-starter/src/main/java/cn/com/qmth/examcloud/core/basic/starter/CoreBasicApp.java

@@ -5,7 +5,6 @@ import cn.com.qmth.examcloud.core.basic.dao.enums.OrgProperty;
 import cn.com.qmth.examcloud.core.basic.service.CryptoConfigService;
 import cn.com.qmth.examcloud.core.basic.service.LoginRuleService;
 import cn.com.qmth.examcloud.core.basic.service.cache.AppCache;
-import cn.com.qmth.examcloud.support.filestorage.FileStorageUtil;
 import cn.com.qmth.examcloud.web.jpa.DataIntegrityViolationTransverter;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 import org.apache.logging.log4j.ThreadContext;
@@ -57,8 +56,6 @@ public class CoreBasicApp {
         SpringApplication.run(CoreBasicApp.class, args);
 
         initCache();
-        FileStorageUtil.initYunSite();
-        FileStorageUtil.initYunClient();
     }
 
     /**