Przeglądaj źródła

增加本地磁盘与OSS两种文件存储模式;增加统一的文件服务接口;增加统一的文件管理类型,调整标准路径格式

luoshi 4 lat temu
rodzic
commit
356508d005

+ 6 - 0
pom.xml

@@ -309,6 +309,12 @@
 				<artifactId>junit</artifactId>
 				<version>4.12</version>
 			</dependency>
+			<!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
+			<dependency>
+				<groupId>com.aliyun.oss</groupId>
+				<artifactId>aliyun-sdk-oss</artifactId>
+				<version>3.10.2</version>
+			</dependency>
 		</dependencies>
 	</dependencyManagement>
 

+ 72 - 67
stmms-biz/pom.xml

@@ -1,67 +1,72 @@
-<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
-	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
-	<modelVersion>4.0.0</modelVersion>
-	<parent>
-		<groupId>cn.com.qmth.stmms</groupId>
-		<artifactId>stmms-parent</artifactId>
-		<version>1.0-SNAPSHOT</version>
-	</parent>
-	<groupId>cn.com.qmth.stmms</groupId>
-	<artifactId>stmms-biz</artifactId>
-	<version>1.0-SNAPSHOT</version>
-	<packaging>jar</packaging>
-	<name>stmms-biz</name>
-	<url>http://maven.apache.org</url>
-
-	<dependencies>
-		<dependency>
-			<groupId>cn.com.qmth.stmms</groupId>
-			<artifactId>stmms-common</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>mysql</groupId>
-			<artifactId>mysql-connector-java</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.springframework.data</groupId>
-			<artifactId>spring-data-jpa</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-entitymanager</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate</groupId>
-			<artifactId>hibernate-ehcache</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.eclipse.persistence</groupId>
-			<artifactId>javax.persistence</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>org.hibernate.javax.persistence</groupId>
-			<artifactId>hibernate-jpa-2.0-api</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>commons-dbcp</groupId>
-			<artifactId>commons-dbcp</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>commons-pool</groupId>
-			<artifactId>commons-pool</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>net.sf.json-lib</groupId>
-			<artifactId>json-lib-ext-spring</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>com.google.guava</groupId>
-			<artifactId>guava</artifactId>
-		</dependency>
-		<dependency>
-			<groupId>junit</groupId>
-			<artifactId>junit</artifactId>
-			<scope>test</scope>
-		</dependency>
-	</dependencies>
-</project>
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>cn.com.qmth.stmms</groupId>
+        <artifactId>stmms-parent</artifactId>
+        <version>1.0-SNAPSHOT</version>
+    </parent>
+    <groupId>cn.com.qmth.stmms</groupId>
+    <artifactId>stmms-biz</artifactId>
+    <version>1.0-SNAPSHOT</version>
+    <packaging>jar</packaging>
+    <name>stmms-biz</name>
+    <url>http://maven.apache.org</url>
+
+    <dependencies>
+        <dependency>
+            <groupId>cn.com.qmth.stmms</groupId>
+            <artifactId>stmms-common</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>mysql</groupId>
+            <artifactId>mysql-connector-java</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.springframework.data</groupId>
+            <artifactId>spring-data-jpa</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-entitymanager</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate</groupId>
+            <artifactId>hibernate-ehcache</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.eclipse.persistence</groupId>
+            <artifactId>javax.persistence</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.hibernate.javax.persistence</groupId>
+            <artifactId>hibernate-jpa-2.0-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-dbcp</groupId>
+            <artifactId>commons-dbcp</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>commons-pool</groupId>
+            <artifactId>commons-pool</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>net.sf.json-lib</groupId>
+            <artifactId>json-lib-ext-spring</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>com.google.guava</groupId>
+            <artifactId>guava</artifactId>
+        </dependency>
+        <!-- https://mvnrepository.com/artifact/com.aliyun.oss/aliyun-sdk-oss -->
+        <dependency>
+            <groupId>com.aliyun.oss</groupId>
+            <artifactId>aliyun-sdk-oss</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>junit</groupId>
+            <artifactId>junit</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

+ 46 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FileType.java

@@ -0,0 +1,46 @@
+package cn.com.qmth.stmms.biz.file.enums;
+
+/**
+ * 所有管理的文件类型
+ */
+public enum FileType {
+
+    SHEET("原图", "sheet/%d/%s/%s-%d.%s"), SLICE("裁切图", "slice/%d/%s/%s-%d.%s"), JSON("作答内容",
+            "json/%d/%s/%s.%s"), PACKAGE("签到表", "package/%d/%s/%d.%s"), PAPER("试卷", "paper/%d/%s.%s"), ANSWER("标答",
+            "answer/%d/%s.%s"), CARD("题卡", "card/%d/%s.%s");
+
+    private String name;
+
+    private String pattern;
+
+    private FileType(String name, String pattern) {
+        this.name = name;
+        this.pattern = pattern;
+    }
+
+    public String getName() {
+        return name;
+    }
+
+    public String getPattern() {
+        return pattern;
+    }
+
+    public boolean equals(String type) {
+        return toString().equalsIgnoreCase(type);
+    }
+
+    public static FileType findByText(String text) {
+        for (FileType type : values()) {
+            if (type.equals(text)) {
+                return type;
+            }
+        }
+        return null;
+    }
+
+    public String getPath(Object... param) {
+        return String.format(pattern, param);
+    }
+
+}

+ 22 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/enums/FormatType.java

@@ -0,0 +1,22 @@
+package cn.com.qmth.stmms.biz.file.enums;
+
+/**
+ * 文件管理支持的格式类型
+ */
+public enum FormatType {
+
+    JPG, JSON, PDF, ZIP;
+
+    public String getExtName() {
+        return toString().toLowerCase();
+    }
+
+    public static FormatType findByText(String text) {
+        for (FormatType type : values()) {
+            if (type.toString().equalsIgnoreCase(text)) {
+                return type;
+            }
+        }
+        return null;
+    }
+}

+ 45 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/FileService.java

@@ -0,0 +1,45 @@
+package cn.com.qmth.stmms.biz.file.service;
+
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+
+import java.io.InputStream;
+import java.util.List;
+
+public interface FileService {
+
+    String getFileServer();
+
+    boolean uploadSheet(InputStream ins, String md5, int examId, String examNumber, int index);
+
+    boolean uploadSlice(InputStream ins, String md5, int examId, String secretNumber, int index);
+
+    boolean uploadJson(InputStream ins, String md5, int examId, String secretNumber);
+
+    boolean uploadPackage(InputStream ins, String md5, int examId, String packageCode, int index);
+
+    boolean uploadPaper(InputStream ins, String md5, int examId, String subjectCode, FormatType type);
+
+    boolean uploadAnswer(InputStream ins, String md5, int examId, String subjectCode, FormatType type);
+
+    boolean uploadCard(InputStream ins, String md5, int examId, String subjectCode, FormatType type);
+
+    String getSheetUri(int examId, String examNumber, int index);
+
+    List<String> getSheetUris(int examId, String examNumber, int start, int end);
+
+    String getSliceUri(int examId, String secretNumber, int index);
+
+    List<String> getSliceUris(int examId, String secretNumber, int start, int end);
+
+    String getJsonUri(int examId, String secretNumber);
+
+    String getPackageUri(int examId, String packageCode, int index);
+
+    List<String> getPackageUris(int examId, String packageCode, int start, int end);
+
+    String getPaperUri(int examId, String subjectCode, FormatType type);
+
+    String getAnswerUri(int examId, String subjectCode, FormatType type);
+
+    String getCardUri(int examId, String subjectCode, FormatType type);
+}

+ 196 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/service/impl/FileServiceImpl.java

@@ -0,0 +1,196 @@
+package cn.com.qmth.stmms.biz.file.service.impl;
+
+import cn.com.qmth.stmms.biz.file.enums.FileType;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
+import cn.com.qmth.stmms.biz.file.service.FileService;
+import cn.com.qmth.stmms.biz.file.store.FileStore;
+import cn.com.qmth.stmms.biz.file.store.impl.DiskStore;
+import cn.com.qmth.stmms.biz.file.store.impl.OssStore;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.factory.InitializingBean;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.InputStream;
+import java.util.LinkedList;
+import java.util.List;
+
+@Service("fileService")
+public class FileServiceImpl implements FileService, InitializingBean {
+
+    private static final String EMPTY_SUBJECT_CODE_PLACEHOLDER = "common";
+
+    private static final int DEFAULT_SUFFIX_LENGTH = 3;
+
+    @Value("${file.server}")
+    private String fileServer;
+
+    @Value("${file.store}")
+    private String fileStore;
+
+    private FileStore store;
+
+    private String getSuffix(String input) {
+        return StringUtils.trimToEmpty(input).substring(Math.max(0, input.length() - DEFAULT_SUFFIX_LENGTH));
+    }
+
+    private boolean checkFormat(FormatType input, FormatType... types) {
+        for (FormatType type : types) {
+            if (type.equals(input)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    @Override
+    public String getFileServer() {
+        return fileServer;
+    }
+
+    public void setFileServer(String fileServer) {
+        this.fileServer = fileServer;
+    }
+
+    public String getFileStore() {
+        return fileStore;
+    }
+
+    public void setFileStore(String fileStore) {
+        this.fileStore = fileStore;
+    }
+
+    @Override
+    public boolean uploadSheet(InputStream ins, String md5, int examId, String examNumber, int index) {
+        return store.write(getSheetUri(examId, examNumber, index), ins, md5);
+    }
+
+    @Override
+    public boolean uploadSlice(InputStream ins, String md5, int examId, String secretNumber, int index) {
+        return store.write(getSliceUri(examId, secretNumber, index), ins, md5);
+    }
+
+    @Override
+    public boolean uploadJson(InputStream ins, String md5, int examId, String secretNumber) {
+        return store.write(getJsonUri(examId, secretNumber), ins, md5);
+    }
+
+    @Override
+    public boolean uploadPackage(InputStream ins, String md5, int examId, String packageCode, int index) {
+        return store.write(getPackageUri(examId, packageCode, index), ins, md5);
+    }
+
+    @Override
+    public boolean uploadPaper(InputStream ins, String md5, int examId, String subjectCode, FormatType type) {
+        return checkFormat(type, FormatType.PDF, FormatType.JSON) && store
+                .write(getPaperUri(examId, subjectCode, type), ins, md5);
+    }
+
+    @Override
+    public boolean uploadAnswer(InputStream ins, String md5, int examId, String subjectCode, FormatType type) {
+        return checkFormat(type, FormatType.PDF, FormatType.JSON) && store
+                .write(getAnswerUri(examId, subjectCode, type), ins, md5);
+    }
+
+    @Override
+    public boolean uploadCard(InputStream ins, String md5, int examId, String subjectCode, FormatType type) {
+        return checkFormat(type, FormatType.ZIP, FormatType.JSON) && store
+                .write(getCardUri(examId, subjectCode != null ? subjectCode : EMPTY_SUBJECT_CODE_PLACEHOLDER, type),
+                        ins, md5);
+    }
+
+    @Override
+    public String getSheetUri(int examId, String examNumber, int index) {
+        return FileType.SHEET.getPath(examId, getSuffix(examNumber), examNumber, index, FormatType.JPG.getExtName());
+    }
+
+    @Override
+    public List<String> getSheetUris(int examId, String examNumber, int start, int end) {
+        List<String> list = new LinkedList<>();
+        for (int i = start; i <= end; i++) {
+            list.add(getSheetUri(examId, examNumber, i));
+        }
+        return list;
+    }
+
+    @Override
+    public String getSliceUri(int examId, String secretNumber, int index) {
+        return FileType.SLICE
+                .getPath(examId, getSuffix(secretNumber), secretNumber, index, FormatType.JPG.getExtName());
+    }
+
+    @Override
+    public List<String> getSliceUris(int examId, String secretNumber, int start, int end) {
+        List<String> list = new LinkedList<>();
+        for (int i = start; i <= end; i++) {
+            list.add(getSliceUri(examId, secretNumber, i));
+        }
+        return list;
+    }
+
+    @Override
+    public String getJsonUri(int examId, String secretNumber) {
+        return FileType.JSON.getPath(examId, getSuffix(secretNumber), secretNumber, FormatType.JSON.getExtName());
+    }
+
+    @Override
+    public String getPackageUri(int examId, String packageCode, int index) {
+        return FileType.PACKAGE.getPath(examId, packageCode, index, FormatType.JPG.getExtName());
+    }
+
+    @Override
+    public List<String> getPackageUris(int examId, String packageCode, int start, int end) {
+        List<String> list = new LinkedList<>();
+        for (int i = start; i <= end; i++) {
+            list.add(getPackageUri(examId, packageCode, i));
+        }
+        return list;
+    }
+
+    @Override
+    public String getPaperUri(int examId, String subjectCode, FormatType type) {
+        return FileType.PAPER.getPath(examId, subjectCode, type.getExtName());
+    }
+
+    @Override
+    public String getAnswerUri(int examId, String subjectCode, FormatType type) {
+        return FileType.ANSWER.getPath(examId, subjectCode, type.getExtName());
+    }
+
+    @Override
+    public String getCardUri(int examId, String subjectCode, FormatType type) {
+        return FileType.ANSWER
+                .getPath(examId, subjectCode != null ? subjectCode : EMPTY_SUBJECT_CODE_PLACEHOLDER, type.getExtName());
+    }
+
+    @Override
+    public void afterPropertiesSet() {
+        fileServer = StringUtils.trimToNull(fileServer);
+        fileStore = StringUtils.trimToNull(fileStore);
+        if (fileServer == null) {
+            throw new RuntimeException("invald property: ${file.server} should not be empty");
+        }
+        if (fileStore == null) {
+            throw new RuntimeException("invald property: ${file.store} should not be empty");
+        }
+        if (fileStore.startsWith("oss")) {
+            store = new OssStore(fileStore);
+        } else {
+            store = new DiskStore(fileStore);
+        }
+    }
+
+    public static void main(String[] args) throws FileNotFoundException {
+        FileServiceImpl service = new FileServiceImpl();
+        service.fileServer = "123";
+        service.fileStore = "oss://LTAI4FnJ2pgV6aGceYcCkeEi:ktrMEVE7PfoxRPeJUPDFeygOIH4aU7@qmth-test.oss-cn-shenzhen.aliyuncs.com";
+        service.afterPropertiesSet();
+
+        //DiskStore ds = new DiskStore("/Users/luoshi/Downloads");
+        //String md5 = BinaryUtil.toBase64String(BinaryUtil.calculateMd5(ds.read("123456.jpg")));
+        System.out.println(service.uploadSheet(new FileInputStream("/Users/luoshi/Downloads/123456.jpg"),
+                "7e9b368ff5da88ff2413c2c9083c481d", 1, "123456", 1));
+    }
+}

+ 10 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/store/FileStore.java

@@ -0,0 +1,10 @@
+package cn.com.qmth.stmms.biz.file.store;
+
+import java.io.InputStream;
+
+public interface FileStore {
+
+    boolean write(String path, InputStream ins, String md5);
+
+    byte[] read(String path);
+}

+ 84 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/store/impl/DiskStore.java

@@ -0,0 +1,84 @@
+package cn.com.qmth.stmms.biz.file.store.impl;
+
+import cn.com.qmth.stmms.biz.file.store.FileStore;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.nio.channels.FileChannel;
+
+/**
+ * 本地磁盘文件管理工具
+ */
+public class DiskStore implements FileStore {
+
+    private static final Logger log = LoggerFactory.getLogger(DiskStore.class);
+
+    private File rootDir;
+
+    public DiskStore(String path) {
+        rootDir = new File(path);
+        if (!rootDir.exists() && !rootDir.mkdirs()) {
+            //自动创建目录失败
+            throw new IllegalArgumentException("[file.store]" + path + ": auto mkdir faile");
+        } else if (rootDir.isFile()) {
+            //判断是否不是目录
+            throw new IllegalArgumentException("[file.store]" + path + ": is a file");
+        }
+    }
+
+    @Override
+    public boolean write(String path, InputStream ins, String md5) {
+        FileOutputStream ous = null;
+        ByteArrayOutputStream buffer = new ByteArrayOutputStream();
+        try {
+            IOUtils.copy(ins, buffer);
+            byte[] data = buffer.toByteArray();
+            if (!BinaryUtil.encodeMD5(data).equalsIgnoreCase(md5)) {
+                throw new RuntimeException("md5 validate faile");
+            }
+            File target = new File(rootDir, path);
+            target.getParentFile().mkdirs();
+            ous = new FileOutputStream(target);
+            ous.write(data);
+            ous.close();
+            return true;
+        } catch (Exception e) {
+            log.error("write file error:" + path, e);
+            return false;
+        } finally {
+            IOUtils.closeQuietly(ous);
+            IOUtils.closeQuietly(buffer);
+        }
+    }
+
+    @Override
+    public byte[] read(String path) {
+        File file = new File(rootDir, path);
+        if (file.exists() && file.isFile()) {
+            FileInputStream ins = null;
+            FileChannel channel = null;
+            try {
+                ins = new FileInputStream(file);
+                channel = ins.getChannel();
+                ByteBuffer byteBuffer = ByteBuffer.allocate((int) channel.size());
+                while ((channel.read(byteBuffer)) > 0) {
+                    //
+                }
+                return byteBuffer.array();
+            } catch (Exception e) {
+                log.error("read file error:" + path, e);
+                return null;
+            } finally {
+                IOUtils.closeQuietly(ins);
+                IOUtils.closeQuietly(channel);
+            }
+        } else {
+            return null;
+        }
+    }
+
+}

+ 86 - 0
stmms-biz/src/main/java/cn/com/qmth/stmms/biz/file/store/impl/OssStore.java

@@ -0,0 +1,86 @@
+package cn.com.qmth.stmms.biz.file.store.impl;
+
+import cn.com.qmth.stmms.biz.file.store.FileStore;
+import cn.com.qmth.stmms.common.utils.Encodes;
+import com.aliyun.oss.OSS;
+import com.aliyun.oss.OSSClientBuilder;
+import com.aliyun.oss.common.utils.BinaryUtil;
+import com.aliyun.oss.model.OSSObject;
+import com.aliyun.oss.model.ObjectMetadata;
+import org.apache.commons.io.IOUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.util.Assert;
+
+import java.io.ByteArrayOutputStream;
+import java.io.InputStream;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+/**
+ * OSS文件管理工具
+ */
+public class OssStore implements FileStore {
+
+    private static final Logger log = LoggerFactory.getLogger(OssStore.class);
+
+    private static final Pattern CONFIG_PATTERN = Pattern.compile("^oss://([\\w]+):([\\w]+)@([\\w-]+).([\\w-.]+)$");
+
+    private String endpoint;
+
+    private String bucket;
+
+    private String accessKey;
+
+    private String accessSecret;
+
+    public OssStore(String config) {
+        String message = "[file.store]" + config + " pattern error";
+        Matcher m = CONFIG_PATTERN.matcher(config);
+        if (m.find()) {
+            accessKey = StringUtils.trimToNull(m.group(1));
+            accessSecret = StringUtils.trimToNull(m.group(2));
+            bucket = StringUtils.trimToNull(m.group(3));
+            endpoint = StringUtils.trimToNull(m.group(4));
+
+            Assert.notNull(accessKey, message);
+            Assert.notNull(accessSecret, message);
+            Assert.notNull(bucket, message);
+            Assert.notNull(endpoint, message);
+
+            endpoint = "https://" + endpoint;
+        } else {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    @Override
+    public boolean write(String path, InputStream ins, String md5) {
+        try {
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessSecret);
+            ObjectMetadata metadata = new ObjectMetadata();
+            metadata.setContentMD5(BinaryUtil.toBase64String(Encodes.decodeHex(md5)));
+            ossClient.putObject(bucket, path, ins, metadata);
+            ossClient.shutdown();
+            return true;
+        } catch (Exception e) {
+            log.error("write file error", e);
+            return false;
+        }
+    }
+
+    @Override
+    public byte[] read(String path) {
+        try {
+            OSS ossClient = new OSSClientBuilder().build(endpoint, accessKey, accessKey);
+            OSSObject ossObject = ossClient.getObject(bucket, path);
+            ByteArrayOutputStream ous = new ByteArrayOutputStream();
+            IOUtils.copy(ossObject.getObjectContent(), ous);
+            return ous.toByteArray();
+        } catch (Exception e) {
+            log.error("read file error", e);
+            return null;
+        }
+    }
+}

+ 40 - 67
stmms-common/src/main/java/cn/com/qmth/stmms/common/utils/Md5EncryptUtils.java

@@ -1,67 +1,40 @@
-package cn.com.qmth.stmms.common.utils;
-
-import java.io.UnsupportedEncodingException;
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-public class Md5EncryptUtils {
-
-    private static final char[] DIGITS = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a',
-            'b', 'c', 'd', 'e', 'f' };
-
-    // 页面编码
-    private static final String CharSet = "utf-8";
-
-    /**
-     * 
-     * @param 明文
-     * @return 密文
-     */
-    public static String md5(String text) {
-        MessageDigest msgDigest = null;
-
-        try {
-            msgDigest = MessageDigest.getInstance("MD5");
-        } catch (NoSuchAlgorithmException e) {
-            throw new IllegalStateException("System doesn't support MD5 algorithm.");
-        }
-
-        try {
-            msgDigest.update(text.getBytes(CharSet)); // 按照utf-8编码形式加密
-
-            byte[] bytes = msgDigest.digest();
-
-            String md5Str = new String(encodeHex(bytes));
-
-            msgDigest.update(md5Str.getBytes(CharSet)); // 按照utf-8编码形式加密
-
-            byte[] bytes1 = msgDigest.digest();
-
-            String str = new String(encodeHex(bytes1));
-
-            return str;
-
-        } catch (UnsupportedEncodingException e) {
-
-            throw new IllegalStateException("System doesn't support your  EncodingException.");
-        } catch (Exception e) {
-
-            throw new IllegalStateException("Exception when Md5 make");
-        }
-    }
-
-    public static char[] encodeHex(byte[] data) {
-
-        int l = data.length;
-
-        char[] out = new char[l << 1];
-
-        // two characters form the hex value.
-        for (int i = 0, j = 0; i < l; i++) {
-            out[j++] = DIGITS[(0xF0 & data[i]) >>> 4];
-            out[j++] = DIGITS[0x0F & data[i]];
-        }
-
-        return out;
-    }
-}
+package cn.com.qmth.stmms.common.utils;
+
+import java.nio.charset.StandardCharsets;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+
+public class Md5EncryptUtils {
+
+    /**
+     * @param text - 明文
+     * @return 密文
+     */
+    public static String md5(String text) {
+        MessageDigest msgDigest = null;
+
+        try {
+            msgDigest = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new IllegalStateException("System doesn't support MD5 algorithm.");
+        }
+
+        try {
+            msgDigest.update(text.getBytes(StandardCharsets.UTF_8)); // 按照utf-8编码形式加密
+
+            byte[] bytes = msgDigest.digest();
+
+            String md5Str = Encodes.encodeHex(bytes);
+
+            msgDigest.update(md5Str.getBytes(StandardCharsets.UTF_8)); // 按照utf-8编码形式加密
+
+            byte[] bytes1 = msgDigest.digest();
+
+            return Encodes.encodeHex(bytes1);
+
+        } catch (Exception e) {
+            throw new IllegalStateException("Exception when Md5 make");
+        }
+    }
+
+}

+ 26 - 0
stmms-web/src/main/java/cn/com/qmth/stmms/common/controller/BaseController.java

@@ -6,6 +6,8 @@ import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
 import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
 import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
 import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
+import cn.com.qmth.stmms.biz.file.enums.FileType;
+import cn.com.qmth.stmms.biz.file.enums.FormatType;
 import cn.com.qmth.stmms.biz.user.model.User;
 import cn.com.qmth.stmms.biz.user.service.UserService;
 import cn.com.qmth.stmms.biz.utils.ScoreCalculateUtil;
@@ -221,6 +223,30 @@ public class BaseController {
                 }
             }
         });
+        // FileType 类型转换
+        binder.registerCustomEditor(FileType.class, new PropertyEditorSupport() {
+
+            @Override
+            public void setAsText(String text) {
+                try {
+                    setValue(FileType.findByText(text));
+                } catch (Exception e) {
+                    setValue(null);
+                }
+            }
+        });
+        // FormatType 类型转换
+        binder.registerCustomEditor(FormatType.class, new PropertyEditorSupport() {
+
+            @Override
+            public void setAsText(String text) {
+                try {
+                    setValue(FormatType.findByText(text));
+                } catch (Exception e) {
+                    setValue(null);
+                }
+            }
+        });
         binder.registerCustomEditor(Boolean.class, new CustomBooleanEditor(true));
     }