功能概述,看代码中注释应该可以理解
- 为了文件安全对url进行适当的保护处理
- 简单的配置功能,如文件大小限制,文件存放位置设定等
- 返回文件内容方法还需完善
代码:
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_FILENAME, 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, "server_vpath"); file_dir = 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 += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!\r\n s_fileId =" + s_fileId; }else{ file.delete(); msg="1"; Logger.Log("文件刪除成功!" + "\r\n s_fileId=" + s_fileId + "\r\n fileName = " + fileName , LOG_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, "server_vpath"); file_dir = 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 += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!\r\n s_fileId =" + s_fileId; }else{ msg=byte2hex(readFile(fileName)); Logger.Log("文件讀取成功!" + "\r\n s_fileId=" + s_fileId + "\r\n fileName = " + fileName , LOG_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, "server_vpath"); file_dir = 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 += "指定的文件不存在,請確認文件路徑與名稱拼寫正確!親,別玩了!\r\n 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 , LOG_FILENAME, 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(); } }
参考:
架设用Webservice实现文件上传功能CentOS服务器(一)
时间: 2024-12-20 09:15:25