浏览代码

文件存储服务商配置更改到系统参数配置中

xiatian 5 年之前
父节点
当前提交
6a05832f91
共有 1 个文件被更改,包括 397 次插入0 次删除
  1. 397 0
      src/main/java/cn/com/qmth/examcloud/support/filestorage/FileStorageUtil.java

+ 397 - 0
src/main/java/cn/com/qmth/examcloud/support/filestorage/FileStorageUtil.java

@@ -0,0 +1,397 @@
+package cn.com.qmth.examcloud.support.filestorage;
+
+import java.io.DataInputStream;
+import java.io.DataOutputStream;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.HttpURLConnection;
+import java.net.URL;
+
+import org.apache.commons.lang3.StringUtils;
+
+import cn.com.qmth.examcloud.commons.exception.StatusException;
+import cn.com.qmth.examcloud.commons.util.MD5;
+import cn.com.qmth.examcloud.support.cache.CacheHelper;
+import cn.com.qmth.examcloud.support.cache.bean.SysPropertyCacheBean;
+import cn.com.qmth.examcloud.web.aliyun.AliyunSiteManager;
+import cn.com.qmth.examcloud.web.filestorage.FileStorage;
+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.filestorage.YunPathInfo;
+import cn.com.qmth.examcloud.web.support.SpringContextHolder;
+import cn.com.qmth.examcloud.web.upyun.UpyunSiteManager;
+
+/**文件存储服务接口工具类
+ * @author 86182
+ *
+ */
+public class FileStorageUtil {
+
+//	private static String fileStorageType = PropertyHolder.getString("$filestorage-type");
+
+//	private static String tempDir = PropertyHolder.getString("$filestorage-trans-tempdir");
+
+	private static String beanSuff = "FileStorage";
+
+
+	
+	/**
+	 * 根据当前配置存储类型保存文件到存储服务器
+	 * 
+	 * @param siteId
+	 * @param env
+	 * @param in   文件流
+	 * @param md5 文件MD5 可为空
+	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
+	 */
+	public static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream in,String md5) {
+		FileStorageType fsType = getFileStorageType();
+		return saveFile(siteId, env, in, fsType,md5);
+	}
+	
+	/**
+	 * 根据当前配置存储类型保存文件到存储服务器
+	 * 
+	 * @param siteId
+	 * @param env
+	 * @param file   文件
+	 * @param withMd5 是否校验MD5
+	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
+	 */
+	public static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, File file,boolean withMd5) {
+		FileStorageType fsType = getFileStorageType();
+		String md5 = null;
+		if (withMd5) {
+			md5 = MD5.md5Hex(file);
+		}
+		return saveFile(siteId, env, file, fsType,md5);
+	}
+	/**
+	 * 根据当前配置存储类型保存文件到存储服务器
+	 * 
+	 * @param siteId
+	 * @param env
+	 * @param file   文件
+	 * @param md5 文件MD5 可为空
+	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
+	 */
+	public static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, File file,String md5) {
+		FileStorageType fsType = getFileStorageType();
+		return saveFile(siteId, env, file, fsType,md5);
+	}
+	/**
+	 * 根据存储类型保存文件到存储服务器
+	 * 
+	 * @param siteId
+	 * @param env
+	 * @param in   文件流
+	 * @param fsType 存储类型
+	 * @param md5 文件MD5 可为空
+	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
+	 */
+	private static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream in, FileStorageType fsType,String md5) {
+		
+		if (siteId == null) {
+			throw new StatusException("1000", "siteId是空");
+		}
+		if (in == null) {
+			throw new StatusException("1001", "文件流是空");
+		}
+		if (env == null) {
+			throw new StatusException("1002", "文件上传路径信息是空");
+		}
+		env.setTimeMillis(String.valueOf(System.currentTimeMillis()));
+		FileStorage fs = SpringContextHolder.getBean(fsType.name().toLowerCase() + beanSuff, FileStorage.class);
+		return fs.saveFile(siteId, env, in,md5);
+	}
+	/**
+	 * 根据存储类型保存文件到存储服务器
+	 * 
+	 * @param siteId
+	 * @param env
+	 * @param file   文件
+	 * @param fsType 存储类型
+	 * @param md5 文件MD5 可为空
+	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
+	 */
+	private static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, File file, FileStorageType fsType,String md5) {
+		if (siteId == null) {
+			throw new StatusException("2000", "siteId是空");
+		}
+		if (file == null) {
+			throw new StatusException("2001", "文件是空");
+		}
+		if (env == null) {
+			throw new StatusException("2002", "文件上传路径信息是空");
+		}
+		env.setTimeMillis(String.valueOf(System.currentTimeMillis()));
+		FileStorage fs = SpringContextHolder.getBean(fsType.name().toLowerCase() + beanSuff, FileStorage.class);
+		return fs.saveFile(siteId, env, file,md5);
+	}
+
+	/**
+	 * 获取文件访问路径
+	 * 
+	 * @param path 数据库保存的路径 如:upyun-1://student_photo/001.jpg,兼容老数据,路径必须是包含根路径的
+	 * @return 可直接访问的文件地址
+	 */
+	public static String realPath(String path) {
+		if(StringUtils.isBlank(path)) {
+			return null;
+		}
+
+		if (StringUtils.isBlank(path)) {
+			throw new StatusException("3001", "文件路径是空");
+		}
+		// 兼容处理老数据文件路径
+		path = diposeOldPath(path);
+		// 如果是全路径直接返回
+		if (path.startsWith("http") || path.startsWith("https")) {
+			return path;
+		}
+		// 根据路径头获取对应的处理类
+		FileStorage fs = SpringContextHolder.getBean(FileStorageHelper.getHead(path).toLowerCase() + beanSuff, FileStorage.class);
+		// 返回处理类处理结果
+		return fs.realPath(path);
+
+	}
+
+	/**
+	 * 将文件转换到指定存储服务上
+	 * 
+	 * @param path        数据库保存的路径
+	 *                    如:upyun-1://student_photo/001.jpg,兼容老数据,路径必须是包含根路径的
+	 * @param transFsType 要转换的类型
+	 * @return 转换之后的路径
+	 */
+//	public static String transPath(String path, FileStorageType transFsType) {
+//		
+//		File file = null;
+//		if (StringUtils.isBlank(path)) {
+//			throw new StatusException("4001", "文件路径是空");
+//		}
+//		if (transFsType == null) {
+//			throw new StatusException("4002", "转换类型是空");
+//		}
+//		// 兼容处理老数据文件路径
+//		path = diposeOldPath(path);
+//		// 如果是全路径直接返回
+//		if (path.startsWith("http") || path.startsWith("https")) {
+//			return path;
+//		}
+//
+//		FileStorageType sourseType = FileStorageType.valueOf(FileStorageHelper.getHead(path));
+//		// 相同的类型直接返回
+//		if (sourseType.equals(transFsType)) {
+//			return path;
+//		}
+//		// 获取对应的处理类
+//		FileStorage fs = SpringContextHolder.getBean(transFsType.name().toLowerCase() + beanSuff, FileStorage.class);
+//		try {
+//			// 下载文件到本地
+//			String httppath = fs.realPath(FileStorageHelper.getPath(path));
+//			file = downFile(httppath);
+//			// 保存文件到指定存储服务器,并返回路径
+//			YunPathInfo ret = fs.saveFile(file, "from" + sourseType.name().toLowerCase() + "/" + FileStorageHelper.getPath(path));
+//			return ret.getRelativePath();
+//		} catch (IOException e) {
+//			throw new StatusException("4003", "下载文件出错 " + e.getMessage());
+//		} finally {
+//			if (file != null) {
+//				file.delete();
+//			}
+//		}
+//
+//	}
+
+//	private static File downFile(String url) throws IOException {
+//		String name = url.substring(url.lastIndexOf("/") + 1);
+//		File file = new File(tempDir + "/" + name);
+//		if (file.exists()) {
+//			file.delete();
+//		}
+//		file.createNewFile();
+//		saveUrlAs(url, file.getAbsolutePath());
+//		return file;
+//	}
+
+	/**
+	 * @param path 数据库存储的路径。路径必须是包含根路径的
+	 * @return 处理后的路径。补全路径头。
+	 */
+	private static String diposeOldPath(String path) {
+		if(StringUtils.isBlank(path)) {
+			return null;
+		}
+		// 如果是全路径直接返回
+		if (path.startsWith("http") || path.startsWith("https")) {
+			return path;
+		}
+		// 如果是半路径,转换成又拍云类型
+		if (path.indexOf(":") == -1) {
+			if (path.startsWith("/")) {
+				path = path.substring(1);
+			}
+			return FileStorageHelper.getUpyunSiteOne(path);
+		}
+		// 无需处理
+		return path;
+	}
+
+
+	/**
+	 * 将网络文件保存到本地
+	 *
+	 * @param fileUrl       网络文件URL
+	 * @param localFilePath 例如D:/123.txt
+	 * @throws IOException
+	 */
+	private static void saveUrlAs(String fileUrl, String localFilePath) throws IOException {
+		URL url = new URL(fileUrl);
+
+		HttpURLConnection connection;
+		connection = (HttpURLConnection) url.openConnection();
+
+		try (DataInputStream dataInputStream = new DataInputStream(connection.getInputStream());
+				FileOutputStream fileOutputStream = new FileOutputStream(localFilePath);
+				DataOutputStream dataOutputStream = new DataOutputStream(fileOutputStream);) {
+
+			byte[] buffer = new byte[4096];
+			int count;
+			while ((count = dataInputStream.read(buffer)) > 0) {
+				dataOutputStream.write(buffer, 0, count);
+			}
+			fileOutputStream.flush();
+			dataOutputStream.flush();
+		} finally {
+			if (connection != null) {
+				connection.disconnect();
+			}
+		}
+	}
+	/**将网络文件保存到本地
+	 * @param fileUrl 网络文件URL
+	 * @param localFile  本地文件对象
+	 * @throws IOException
+	 */
+	public static void saveUrlAs(String fileUrl, File localFile)  {
+		try {
+			saveUrlAs(fileUrl, localFile.getAbsolutePath());
+		} catch (IOException e) {
+			throw new StatusException("5001", "下载文件出错",e);
+		}
+	}
+
+	/**获取指定云存储的签名
+	 * @param siteId
+	 * @param env
+	 * @param md5
+	 * @return
+	 */
+	public static YunHttpRequest getSignature(FileStorageType fsType,String siteId, FileStoragePathEnvInfo env, String md5) {
+		env.setTimeMillis(String.valueOf(System.currentTimeMillis()));
+		// 获取对应的处理类
+		FileStorage fs = SpringContextHolder.getBean(fsType.name().toLowerCase() + beanSuff, FileStorage.class);
+		return fs.getSignature(siteId, env, md5);
+	}
+
+	
+	/**获取完整的不带域名的路径
+	 * @param prefixPath 路径前缀
+	 * @param sourcePath 数据库存储的路径
+	 * @return 处理之后的路径
+	 */
+	public static String getIntactPath(String prefixPath,String sourcePath) {
+		if(StringUtils.isBlank(sourcePath)) {
+			return null;
+		}
+		// 如果是全路径直接返回
+		if (sourcePath.startsWith("http") || sourcePath.startsWith("https")) {
+			return sourcePath;
+		}
+		// 如果是半路径则拼接
+		if (sourcePath.indexOf(":") == -1) {
+			if (sourcePath.startsWith("/")) {
+				sourcePath = sourcePath.substring(1);
+			}
+			if (prefixPath.endsWith("/")) {
+				prefixPath = prefixPath.substring(0,prefixPath.length());
+			}
+			return prefixPath+"/"+sourcePath;
+		}
+		// 新协议无需处理
+		return sourcePath;
+	}
+	
+	
+	/**删除云存储文件
+	 * @param path 全路径,包含根目录,含协议名
+	 */
+	public static void deleteFile(String path) {
+		if(StringUtils.isBlank(path)) {
+			return;
+		}
+		path=diposeOldPath(path);
+		// 如果是全路径直接返回
+		if (path.startsWith("http") || path.startsWith("https")) {
+			return;
+		}
+		FileStorage fs = SpringContextHolder.getBean(FileStorageHelper.getHead(path).toLowerCase() + beanSuff, FileStorage.class);
+		fs.deleteFile(path);
+	}
+	
+	/**
+	 * 获取文件访问路径(备用域名地址)
+	 * 
+	 * @param path 数据库保存的路径 如:upyun-1://student_photo/001.jpg,兼容老数据,路径必须是包含根路径的
+	 * @return 可直接访问的文件地址,如果没有配置备用地址,则返回主域名地址
+	 */
+	public static String realPathBackup(String path) {
+		if(StringUtils.isBlank(path)) {
+			return null;
+		}
+		if (StringUtils.isBlank(path)) {
+			throw new StatusException("6001", "文件路径是空");
+		}
+		// 兼容处理老数据文件路径
+		path = diposeOldPath(path);
+		// 如果是全路径直接返回
+		if (path.startsWith("http") || path.startsWith("https")) {
+			return path;
+		}
+		// 根据路径头获取对应的处理类
+		FileStorage fs = SpringContextHolder.getBean(FileStorageHelper.getHead(path).toLowerCase() + beanSuff, FileStorage.class);
+		// 返回处理类处理结果
+		return fs.realPathBackup(path);
+
+	}
+	
+	
+	public static void initYunClient() {
+		UpyunSiteManager.initClient();
+		AliyunSiteManager.initClient();
+	}
+	public static void initYunSite() {
+		UpyunSiteManager.initSite();
+		AliyunSiteManager.initSite();
+	}
+	
+
+	public static FileStorageType getFileStorageType() {
+		SysPropertyCacheBean spc = CacheHelper.getSysProperty("filestorage.type");
+        if (spc == null || spc.getValue() == null) {
+        	throw new StatusException("10001", "未配置文件存储服务类型");
+        }
+        String type=(String)spc.getValue();
+        try {
+        	return FileStorageType.valueOf(type);
+		} catch (Exception e) {
+			throw new StatusException("10002", "配置文件存储服务类型错误");
+		}
+	}
+	
+}