架设用Webservice实现文件上传功能CentOS服务器(二)--WebService
发布时间:2020-12-16 23:20:55 所属栏目:安全 来源:网络整理
导读:功能概述,看代码中注释应该可以理解 为了文件安全对url进行适当的保护处理 简单的配置功能,如文件大小限制,文件存放位置设定等 返回文件内容方法还需完善 代码: import java.io.File;import java.io.FileInputStream;import java.io.FileOutputStream;im
功能概述,看代码中注释应该可以理解
代码: import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.text.SimpleDateFormat; import java.util.Date; import java.util.UUID; import common.IniEditor; import common.Logger; import common.SecurityUtil; /** ?* 文件上傳Web Service 組件,提供給AP使用,AP文件統一存放在File Server而非DB,以方便集中管理AP 所產生文件,並且避免因大量文件存放DB而導致DB管理(如備份)問題。 ?*該組件主要提供: ?*<ol> ?*<li> ?*<b>文件上傳保存:</b>由AP提供目錄規劃,按目錄存放文件,AP 只保存該接口返回的File ID;並提供隱藏存放路徑的保密措施; ?*</li> ?*<li> ?*<b>文件刪除:</b>AP 提供File ID(加密後),刪除指定文件; ?*</li> ? ? *<li> ?*<b>取得文件:</b>AP 提供File ID(加密後),返回指定文件路徑,或文件內容(二進制); ?*</li> ? ?*@version 1.0 ?* ?* @author rayd ?* ?*/ public class FileService { ?? ?private final static String LOG_FILENAME = "fileserver.log"; ?? ?private final static String LOG_FILENAME_ERROR = "fileserver_error.log"; ?? ?private final static String CFG_FILESERVER = "fileserver"; ?? ?private final static String LINE_BIAS = "/"; ?? ?private final static String ERROR_FLAG= "error_"; ?? ?/** ?? ? * 上傳文件,依照AP 提供的路徑存放文件,爲文件安全考慮,每次均當作一份新的文件進行保存,即使是同一份文件也不會覆蓋,若要覆蓋,請調用者先執行@see deleteFile 刪除 命令。 ?? ? * @param b_bytes 文件內容,二進制,Default最大10M,可設定 ?? ? * @param s_path 存放路徑,如/131/purchase/po1310001,該接口會按年月區分目錄,如以上目錄實際會保存到”/201409/131/purchase/po1310001“目錄。 ?? ? * @param s_extName 文件类别,可以爲pdf/.pdf/test.pdf ?? ? * @return File ID ,進加密處理的文件識別ID ;若不成功,將返回以error_開頭的信息,AP 可以此作爲成功與否的判斷。 ?? ? * ?? ? */ ?? ?public String uploadFile(byte[] b_bytes,String s_path,String s_extName){ ?? ??? ?StringBuilder retUrl = new StringBuilder(); ?? ??? ?StringBuilder sbEncrypt = new StringBuilder(); ?? ??? ?String msg = ERROR_FLAG; ?? ??? ?String filePath = ""; ?? ??? ?String fileName = ""; ?? ??? ?String extName = ""; ?? ??? ?String file_dir = ""; ?? ??? ?String log_dir = ""; ?? ??? ?String ymPath = ""; ?? ??? ?String path_first = ""; ?? ??? ?String server_vpath=""; ?? ??? ?String server_host=""; ?? ??? ?String customPath=""; ?? ??? ?//String encrypt_path=""; ?? ??? ?Date date; ?? ??? ?SimpleDateFormat df; ?? ??? ?UUID uuid; ?? ??? ?int max_size = 0; ?? ??? ? ?? ??? ?//get config value ?? ??? ?try { ?? ??? ??? ?//get ini value ?? ??? ??? ?max_size = Integer.parseInt(getConfig(CFG_FILESERVER,"max_size")); ?? ??? ??? ?path_first = getConfig(CFG_FILESERVER,"path_first"); ?? ??? ??? ?server_host = getConfig(CFG_FILESERVER,"server_host"); ?? ??? ??? ?server_vpath = getConfig(CFG_FILESERVER,"server_vpath"); ?? ??? ??? ?file_dir = getConfig(CFG_FILESERVER,"file_dir"); ?? ??? ??? ?//log path ?? ??? ??? ?log_dir = file_dir + File.separator + "log" + File.separator; ?? ??? ??? ? ?? ??? ?} catch (NumberFormatException e1) { ?? ??? ??? ?msg += "可能缺少必要的配置項,或max_size配置項值應爲數字!"; ?? ??? ??? ?return msg; ?? ??? ?} catch (Exception e1) { ?? ??? ??? ?msg += "系統配置讀取異常,可能缺少必要的配置項!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?// 前置检查 ?? ??? ?if (b_bytes == null || b_bytes.length == 0) { ?? ??? ??? ?msg += "沒有接收到任何文件內容,這樣來去空空不失望嗎?"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//path ?? ??? ?if (s_path == null || s_path.length() == 0) { ?? ??? ??? ?msg += "請指定文件存放路徑,如 /po/no/,不知要放到哪裏,真是要到Cloud端嗎?"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//filename ?? ??? ?if (s_extName == null || s_extName.length() == 0) { ?? ??? ??? ?msg += "請指定文件類型,如.pdf or pdf or abc.pdf!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ? ?? ??? ?// size限制,设定max_size为0时,不限制; ?? ??? ?if (max_size != 0 && b_bytes.length > 1024 * 1024 * max_size) { ?? ??? ??? ?msg += "上傳文件過大,好吧,別再挑戰人類的極限!"; ?? ??? ??? ?Logger.Log(msg,LOG_FILENAME_ERROR,log_dir); ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?retUrl.append(server_host).append(server_vpath); ?? ??? ?date = new Date(); ?? ??? ?if (path_first.isEmpty() || path_first.equalsIgnoreCase("none")) { ?? ??? ?} else { ?? ??? ??? ?retUrl.append(LINE_BIAS); ?? ??? ??? ?//? yyyyMM or yyyy/MM ?? ??? ??? ?df = new SimpleDateFormat(path_first); ?? ??? ??? ?ymPath = df.format(date).toString(); ?? ??? ?} ?? ??? ?sbEncrypt.append(ymPath); ?? ??? ? ?? ??? ?// guid做为文件名称 ?? ??? ?uuid = UUID.randomUUID(); ?? ??? ?// "" to "/" ?? ??? ?customPath = s_path.replace("",LINE_BIAS); ?? ??? ?// po012.pdf ?? ??? ?// .pdf ?? ??? ?// pdf ?? ??? ?int pos1 = s_extName.lastIndexOf('.'); ?? ??? ?if (pos1 >= 0) { ?? ??? ??? ?extName = s_extName.substring(pos1); ?? ??? ?} else { ?? ??? ??? ?extName = "." + s_extName; ?? ??? ?} ?? ??? ?fileName = uuid.toString() + extName; ?? ??? ?filePath = file_dir + File.separator + ymPath; ?? ??? ?if (!customPath.startsWith(LINE_BIAS)) { ?? ??? ??? ?filePath += File.separator; ?? ??? ??? ?sbEncrypt.append(LINE_BIAS); ?? ??? ?} ?? ??? ?filePath += customPath; ?? ??? ?sbEncrypt.append(customPath); ?? ??? ?if (!customPath.endsWith(LINE_BIAS)) { ?? ??? ??? ?filePath += File.separator; ?? ??? ??? ?sbEncrypt.append(LINE_BIAS); ?? ??? ?} ?? ??? ?sbEncrypt.append(fileName); ?? ??? ?FileOutputStream fos = null; ?? ??? ? ?? ??? ?try { ?? ??? ??? ? ?? ??? ??? ? ?? ??? ??? ?File file = new File(filePath); ?? ??? ??? ?// 创建多个目录 ?? ??? ??? ?if (!file.exists()) ?? ??? ??? ??? ?file.mkdirs(); ?? ??? ??? ?fos = new FileOutputStream(filePath + fileName); ?? ??? ??? ?fos.write(b_bytes); ?? ??? ??? ?fos.flush(); ?? ??? ??? ? ?? ??? ??? ?msg = SecurityUtil.encryptPath(retUrl.toString(),sbEncrypt.toString()); ?? ??? ??? ?Logger.Log("文件保存成功:" + retUrl.toString()+sbEncrypt.toString(),LOG_FILENAME,log_dir); ?? ??? ??? ?//Logger.Log("密碼:" + msg,log_dir); ?? ??? ?} catch (IOException ex) { ?? ??? ??? ?msg = "文件存儲失敗:" + ex.getMessage(); ?? ??? ??? ?Logger.Log(msg + "ErrMsg: " + ex.getStackTrace(),?? ??? ??? ??? ??? ?LOG_FILENAME_ERROR,log_dir); ?? ??? ?} catch (Exception e) { ?? ??? ??? ? ?? ??? ?} finally { ?? ??? ??? ?if (fos != null) ?? ??? ??? ??? ?try { ?? ??? ??? ??? ??? ?fos.close(); ?? ??? ??? ??? ?} catch (IOException e) { ?? ??? ??? ??? ??? ?//e.printStackTrace(); ?? ??? ??? ??? ??? ?msg += "上傳文件不能正常關閉,這狀況真的是千古難遇,建議您去買彩票!"; ?? ??? ??? ??? ??? ?Logger.Log(msg + " ErrMsg: " + e.getStackTrace(),?? ??? ??? ??? ??? ??? ??? ?LOG_FILENAME_ERROR,log_dir); ?? ??? ??? ??? ?} ?? ??? ?} ?? ??? ?return msg; ?? ?} ?? ?/** ?? ? * 刪除指定的文件 ?? ? * @param s_fileId AP保留的FileID ?? ? * @return 返回信息,1:代表刪除成功,其他代碼失敗信息;若不成功,將返回以error_開頭的信息,AP 可以此作爲成功與否的判斷。 ?? ? * ?? ? */ ?? ?public String deleteFile(String s_fileId){ ?? ??? ?String msg = ERROR_FLAG; ?? ??? ?String filePath; ?? ??? ? ?? ??? ?String fileName = ""; ?? ??? ?String file_dir = ""; ?? ??? ?String log_dir = ""; ?? ??? ?String server_vpath=""; ?? ??? ? ?? ??? ?if(s_fileId.isEmpty()){ ?? ??? ??? ?msg += "沒有傳入任何路徑與文件!親,又調皮了!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//get config value ?? ??? ?try { ?? ??? ??? ?//get ini value ?? ??? ??? ?server_vpath = getConfig(CFG_FILESERVER,"file_dir"); ?? ??? ??? ?//log path ?? ??? ??? ?log_dir = file_dir + File.separator + "log" + File.separator; ?? ??? ??? ?filePath = SecurityUtil.decryptPath(s_fileId); ?? ??? ??? ?int pos1 = filePath.indexOf(server_vpath); ?? ??? ??? ?fileName = file_dir +filePath.substring(pos1+server_vpath.length()) ; ?? ??? ??? ?File file = new File(fileName); ?? ??? ??? ? ?? ??? ??? ?if (!file.exists()){ ?? ??? ??? ??? ?msg += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!rn s_fileId =" + s_fileId; ?? ??? ??? ?}else{ ?? ??? ??? ??? ?file.delete(); ?? ??? ? ?? ??? ??? ??? ?msg="1"; ?? ??? ??? ??? ?Logger.Log("文件刪除成功!" + "rn s_fileId=" + s_fileId + "rn fileName = " + fileName,log_dir); ?? ??? ??? ?} ?? ??? ?} catch (Exception e1) { ?? ??? ??? ?msg += "文件刪除異常!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//file.deleteOnExit(); ?? ??? ?return msg; ?? ?} ?? ? ?? ?/** ?? ? * 讀取指定的文件,以二進制內容返回 ?? ? * @param s_fileId AP保留的File ID ?? ? * @return 返回文件二進制內容,若讀取失敗,將返回以error_開頭的信息,AP 可以此作爲成功與否的判斷。 ?? ? * ?? ? * ?? ? */ ?? ?public String getFile(String s_fileId){ ?? ??? ?String msg = ERROR_FLAG; ?? ??? ?String filePath; ?? ??? ? ?? ??? ?String fileName = ""; ?? ??? ?String file_dir = ""; ?? ??? ?String log_dir = ""; ?? ??? ?String server_vpath=""; ?? ??? ? ?? ??? ?if(s_fileId.isEmpty()){ ?? ??? ??? ?msg += "沒有傳入任何路徑與文件!親,又調皮了!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//get config value ?? ??? ?try { ?? ??? ??? ?//get ini value ?? ??? ??? ?server_vpath = getConfig(CFG_FILESERVER,"file_dir"); ?? ??? ??? ?//log path ?? ??? ??? ?log_dir = file_dir + File.separator + "log" + File.separator; ?? ??? ??? ?filePath = SecurityUtil.decryptPath(s_fileId); ?? ??? ??? ?int pos1 = filePath.indexOf(server_vpath); ?? ??? ??? ?fileName = file_dir +filePath.substring(pos1+server_vpath.length()) ; ?? ??? ??? ?File file = new File(fileName); ?? ??? ??? ? ?? ??? ??? ?if (!file.exists()){ ?? ??? ??? ??? ?msg += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!rn s_fileId =" + s_fileId; ?? ??? ??? ?}else{ ?? ??? ??? ??? ? ?? ??? ??? ??? ?msg=byte2hex(readFile(fileName)); ?? ??? ??? ??? ?Logger.Log("文件讀取成功!" + "rn s_fileId=" + s_fileId + "rn fileName = " + fileName,log_dir); ?? ??? ??? ?} ?? ??? ?} catch (Exception e1) { ?? ??? ??? ?msg += "文件讀取異常!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//file.deleteOnExit(); ?? ??? ?return msg; ?? ?} ?? ? ?? ?/** ?? ? * 取得指定的文件URL ?? ? * @param s_fileId AP保留的FileID ?? ? * @return 文件明文路徑,若讀取失敗,將返回以error_開頭的信息,AP 可以此作爲成功與否的判斷。 ?? ? * ?? ? ?? ? */ ?? ?public String getFileUrl(String s_fileId){ ?? ??? ?String msg = ERROR_FLAG; ?? ??? ?String filePath; ?? ??? ? ?? ??? ?String fileName = ""; ?? ??? ?String file_dir = ""; ?? ??? ?String log_dir = ""; ?? ??? ?String server_vpath=""; ?? ??? ? ?? ??? ?if(s_fileId.isEmpty()){ ?? ??? ??? ?msg += "沒有傳入任何路徑與文件!親,又調皮了!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//get config value ?? ??? ?try { ?? ??? ??? ?//get ini value ?? ??? ??? ?server_vpath = getConfig(CFG_FILESERVER,"file_dir"); ?? ??? ??? ?//log path ?? ??? ??? ?log_dir = file_dir + File.separator + "log" + File.separator; ?? ??? ??? ?filePath = SecurityUtil.decryptPath(s_fileId); ?? ??? ??? ?int pos1 = filePath.indexOf(server_vpath); ?? ??? ??? ?fileName = file_dir +filePath.substring(pos1+server_vpath.length()) ; ?? ??? ??? ?File file = new File(fileName); ?? ??? ??? ? ?? ??? ??? ?if (!file.exists()){ ?? ??? ??? ??? ?msg += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!rn s_fileId =" + s_fileId; ?? ??? ??? ?}else{ ?? ??? ??? ??? ?msg = filePath; ?? ??? ??? ?} ?? ??? ?} catch (Exception e1) { ?? ??? ??? ?msg += "文件取得異常!"; ?? ??? ??? ?return msg; ?? ??? ?} ?? ??? ?//file.deleteOnExit(); ?? ??? ?return msg; ?? ?} ?? ? ?? ? ?? ? ?? ?// get ini config file ?? ?private String getConfig(String s_section,String s_name){ ?? ??? ?String val = ""; ?? ??? ?String msg = ""; ?? ??? ?String rootPath =getClass().getProtectionDomain().getCodeSource() ?? ??? ??? ??? ?.getLocation().getPath(); ?? ??? ?String iniFile = rootPath?? ?+ "fileservice.ini"; ?? ??? ? ?? ??? ?IniEditor conf = new IniEditor(); ?? ??? ?try { ?? ??? ??? ?conf.load(iniFile); ?? ??? ?} catch (IOException e) { ?? ??? ??? ?msg = "配置文件(fileservice.ini)不存在或讀取異常!"; ?? ??? ??? ?Logger.Log(msg,rootPath); ?? ??? ?} ?? ??? ?val = conf.get(s_section,s_name); ?? ??? ?return val; ?? ?} ?? ? ?? ?//讀取文件 ?? ?private static byte[] readFile(String fileName) { ?? ??? ?File file = new File(fileName); ?? ??? ?byte[] buffer = null; ?? ??? ?InputStream in = null; ?? ??? ?try { ?? ??? ??? ?// 一次读一个字节 ?? ??? ??? ?in = new FileInputStream(file); ?? ??? ??? ?buffer = new byte[in.available()]; ?? ??? ??? ?in.read(buffer); ?? ??? ?} catch (IOException e) { ?? ??? ??? ?e.printStackTrace(); ?? ??? ?} ?? ??? ?return buffer; ?? ?} ?? ? ?? ?// 二进制转字符串 ? ?? ?private static String byte2hex(byte[] b)? ? ?? ?{ ? ?? ??? StringBuffer sb = new StringBuffer(); ? ?? ??? String tmp = ""; ? ?? ??? for (int i = 0; i < b.length; i++) { ? ?? ???? tmp = Integer.toHexString(b[i] & 0XFF); ? ?? ???? if (tmp.length() == 1){ ? ?? ???????? sb.append("0" + tmp); ? ?? ???? }else{ ? ?? ???????? sb.append(tmp); ? ?? ???? } ? ?? ????? ? ?? ??? } ? ?? ??? return sb.toString(); ? ?? ?} ? } 参考: (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |