xiatian 5 rokov pred
rodič
commit
3fd415a65a

+ 12 - 0
src/main/java/cn/com/qmth/examcloud/web/filestorage/FileStorage.java

@@ -1,8 +1,19 @@
 package cn.com.qmth.examcloud.web.filestorage;
 
 import java.io.File;
+import java.io.InputStream;
 
 public interface FileStorage {
+	
+	/**保存文件到存储服务
+	 * @param siteId 
+	 * @param env
+	 * @param file 文件流
+	 * @param md5 文件MD5 可为空
+	 * @return 返回路径
+	 */
+	public YunPathInfo saveFile(String siteId,FileStoragePathEnvInfo env,InputStream in,String md5);
+	
 	/**保存文件到存储服务
 	 * @param siteId 
 	 * @param env
@@ -10,6 +21,7 @@ public interface FileStorage {
 	 * @param md5 文件MD5 可为空
 	 * @return 返回路径
 	 */
+	
 	public YunPathInfo saveFile(String siteId,FileStoragePathEnvInfo env,File file,String md5);
 	
 	/**获取可直接访问的文件地址

+ 45 - 4
src/main/java/cn/com/qmth/examcloud/web/filestorage/FileStorageUtil.java

@@ -12,6 +12,7 @@ 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.web.bootstrap.PropertyHolder;
 import cn.com.qmth.examcloud.web.support.SpringContextHolder;
 
@@ -29,13 +30,31 @@ public class FileStorageUtil {
 	 * 
 	 * @param siteId
 	 * @param env
-	 * @param file   文件流
+	 * @param in   文件流
 	 * @param md5 文件MD5 可为空
 	 * @return 返回包含协议名的地址,数据库直接存储用 如:upyun-1://student_photo/001.jpg
 	 */
-	public static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream file,String md5) {
+	public static YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream in,String md5) {
 		FileStorageType fsType = FileStorageType.valueOf(fileStorageType);
-		return null;
+		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 = FileStorageType.valueOf(fileStorageType);
+		String md5 = null;
+		if (withMd5) {
+			md5 = MD5.md5Hex(file);
+		}
+		return saveFile(siteId, env, file, fsType,md5);
 	}
 	/**
 	 * 根据当前配置存储类型保存文件到存储服务器
@@ -50,7 +69,29 @@ public class FileStorageUtil {
 		FileStorageType fsType = FileStorageType.valueOf(fileStorageType);
 		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", "文件上传路径信息是空");
+		}
+		FileStorage fs = SpringContextHolder.getBean(fsType.name().toLowerCase() + beanSuff, FileStorage.class);
+		return fs.saveFile(siteId, env, in,md5);
+	}
 	/**
 	 * 根据存储类型保存文件到存储服务器
 	 * 

+ 161 - 2
src/main/java/cn/com/qmth/examcloud/web/filestorage/impl/AliyunFileStorageImpl.java

@@ -6,6 +6,7 @@ import java.io.DataOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.OutputStream;
 import java.net.HttpURLConnection;
@@ -94,7 +95,12 @@ public class AliyunFileStorageImpl implements FileStorage {
 
 		String filepath = file.getAbsolutePath();
 		String filename = path.substring(path.lastIndexOf("/") + 1);
-		String urlStr = ossEndpoint.replace("http://", "http://" + bucket + "."); // 提交表单的URL为bucket域名
+		String urlStr = null; // 提交表单的URL为bucket域名
+		if(ossEndpoint.startsWith("https://")) {
+			urlStr = ossEndpoint.replace("https://", "https://" + bucket + "."); 
+		}else if(ossEndpoint.startsWith("http://")) {
+			urlStr = ossEndpoint.replace("http://", "http://" + bucket + "."); 
+		}
 
 		LinkedHashMap<String, String> textMap = new LinkedHashMap<String, String>();
 		// key
@@ -250,7 +256,12 @@ public class AliyunFileStorageImpl implements FileStorage {
 		String bucket = ac.getBucket();
 		String accessKeyId = ac.getAccessKeyId();
 		String accessKeySecret = ac.getAccessKeySecret();
-		String urlStr = ossEndpoint.replace("http://", "http://" + bucket + ".");
+		String urlStr = null; // 提交表单的URL为bucket域名
+		if(ossEndpoint.startsWith("https://")) {
+			urlStr = ossEndpoint.replace("https://", "https://" + bucket + "."); 
+		}else if(ossEndpoint.startsWith("http://")) {
+			urlStr = ossEndpoint.replace("http://", "http://" + bucket + "."); 
+		}
 		env.setTimeMillis(String.valueOf(System.currentTimeMillis()));
 
 		String path = FreeMarkerUtil.process(site.getPath(), env);
@@ -289,4 +300,152 @@ public class AliyunFileStorageImpl implements FileStorage {
 		// TODO Auto-generated method stub
 		
 	}
+	
+	private  String postObjectByInputStream(String siteId, FileStoragePathEnvInfo env, InputStream in, String md5) throws IOException {
+		AliyunSite as = AliyunSiteManager.getAliyunSite(siteId);
+		AliYunAccount ac = AliyunSiteManager.getAliYunAccountByAliyunId(as.getAliyunId());
+		String ossEndpoint = ac.getOssEndpoint();
+		String bucket = ac.getBucket();
+		String accessKeyId = ac.getAccessKeyId();
+		String accessKeySecret = ac.getAccessKeySecret();
+		// 阿里云文件路径
+		String path = FreeMarkerUtil.process(as.getPath(), env);
+		if (path.startsWith("/")) {
+			path = path.substring(1);
+		}
+
+		String filename = path.substring(path.lastIndexOf("/") + 1);
+		String urlStr = null; // 提交表单的URL为bucket域名
+		if(ossEndpoint.startsWith("https://")) {
+			urlStr = ossEndpoint.replace("https://", "https://" + bucket + "."); 
+		}else if(ossEndpoint.startsWith("http://")) {
+			urlStr = ossEndpoint.replace("http://", "http://" + bucket + "."); 
+		}
+
+		LinkedHashMap<String, String> textMap = new LinkedHashMap<String, String>();
+		// key
+		textMap.put("key", path);
+		// Content-Disposition
+		textMap.put("Content-Disposition", "attachment;filename=" + filename);
+		// OSSAccessKeyId
+		textMap.put("OSSAccessKeyId", accessKeyId);
+		// policy
+		String policy = "{\"expiration\": \"2120-01-01T12:00:00.000Z\",\"conditions\": [[\"content-length-range\", 0, "
+				+ maxFileSize + "]]}";
+		String encodePolicy = java.util.Base64.getEncoder().encodeToString(policy.getBytes());
+		textMap.put("policy", encodePolicy);
+		// Signature
+		String signaturecom = com.aliyun.oss.common.auth.ServiceSignature.create().computeSignature(accessKeySecret,
+				encodePolicy);
+		textMap.put("Signature", signaturecom);
+
+
+		String ret = formUploadByInputStream(urlStr, textMap, in,filename);
+		log.info("oss上传:" + ret);
+		return path;
+	}
+
+	@SuppressWarnings("rawtypes")
+	private static String formUploadByInputStream(String urlStr, Map<String, String> textMap, InputStream filein,String fileName )
+			throws IOException {
+		String res = "";
+		HttpURLConnection conn = null;
+		String BOUNDARY = "9431149156168";
+		try {
+			URL url = new URL(urlStr);
+			conn = (HttpURLConnection) url.openConnection();
+			conn.setConnectTimeout(5000);
+			conn.setReadTimeout(30000);
+			conn.setDoOutput(true);
+			conn.setDoInput(true);
+			conn.setRequestMethod("POST");
+			conn.setRequestProperty("User-Agent", "Mozilla/5.0 (Windows; U; Windows NT 6.1; zh-CN; rv:1.9.2.6)");
+			conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY);
+
+			OutputStream out = new DataOutputStream(conn.getOutputStream());
+			// text
+			if (textMap != null) {
+				StringBuffer strBuf = new StringBuffer();
+				Iterator iter = textMap.entrySet().iterator();
+				int i = 0;
+				while (iter.hasNext()) {
+					Map.Entry entry = (Map.Entry) iter.next();
+					String inputName = (String) entry.getKey();
+					String inputValue = (String) entry.getValue();
+					if (inputValue == null) {
+						continue;
+					}
+					if (i == 0) {
+						strBuf.append("--").append(BOUNDARY).append("\r\n");
+						strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
+						strBuf.append(inputValue);
+					} else {
+						strBuf.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
+						strBuf.append("Content-Disposition: form-data; name=\"" + inputName + "\"\r\n\r\n");
+
+						strBuf.append(inputValue);
+					}
+
+					i++;
+				}
+				out.write(strBuf.toString().getBytes());
+			}
+
+			// file
+
+					StringBuffer strBufFile = new StringBuffer();
+					strBufFile.append("\r\n").append("--").append(BOUNDARY).append("\r\n");
+					strBufFile.append("Content-Disposition: form-data; name=\"file\"; filename=\"" + fileName
+							+ "\"\r\n");
+					strBufFile.append("Content-Type: application/octet-stream\r\n\r\n");
+
+					out.write(strBufFile.toString().getBytes());
+
+					DataInputStream in = new DataInputStream(filein);
+					int bytes = 0;
+					byte[] bufferOut = new byte[1024];
+					while ((bytes = in.read(bufferOut)) != -1) {
+						out.write(bufferOut, 0, bytes);
+					}
+					in.close();
+				StringBuffer strBufTag = new StringBuffer();
+				out.write(strBufTag.toString().getBytes());
+
+			byte[] endData = ("\r\n--" + BOUNDARY + "--\r\n").getBytes();
+			out.write(endData);
+			out.flush();
+			out.close();
+
+			// 读取返回数据
+			StringBuffer strBuf = new StringBuffer();
+			BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()));
+			String line = null;
+			while ((line = reader.readLine()) != null) {
+				strBuf.append(line).append("\n");
+			}
+			res = strBuf.toString();
+			reader.close();
+			reader = null;
+		} finally {
+			if (conn != null) {
+				conn.disconnect();
+				conn = null;
+			}
+		}
+		return res;
+	}
+
+	@Override
+	public YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream in, String md5) {
+		try {
+			String relativePath = postObjectByInputStream(siteId, env, in, null);
+			AliyunSite as = AliyunSiteManager.getAliyunSite(siteId);
+			AliYunAccount ac = AliyunSiteManager.getAliYunAccountByAliyunId(as.getAliyunId());
+			String url=FileStorageUtil.getUrl(ac.getDomain(), relativePath);
+			YunPathInfo pi=new YunPathInfo(url, FileStorageType.ALIYUN + "-" + as.getAliyunId() + "://" + relativePath);
+			return pi;
+		} catch (IOException e) {
+			throw new StatusException("6001", "上传出错", e);
+		}
+	}
 }

+ 12 - 0
src/main/java/cn/com/qmth/examcloud/web/filestorage/impl/UpyunFileStorageImpl.java

@@ -1,6 +1,7 @@
 package cn.com.qmth.examcloud.web.filestorage.impl;
 
 import java.io.File;
+import java.io.InputStream;
 
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
@@ -89,4 +90,15 @@ public class UpyunFileStorageImpl implements FileStorage {
 		
 	}
 
+	@Override
+	public YunPathInfo saveFile(String siteId, FileStoragePathEnvInfo env, InputStream in, String md5) {
+		UpYunPathInfo pathInfo =upyunService.writeFile(siteId, of(env), in, md5);
+		UpyunSite site=UpyunSiteManager.getUpyunSite(siteId);
+		String relativePath=FileStorageType.UPYUN+"-"+site.getUpyunId()+"://"+pathInfo.getRelativePath();
+		UpYunClient c=UpyunSiteManager.getUpYunClientByUpyunId(site.getUpyunId());
+		String url=FileStorageUtil.getUrl(c.getDomain(), pathInfo.getRelativePath());
+		YunPathInfo pi=new YunPathInfo(url, relativePath);
+		return pi;
+	}
+
 }