首页 > 代码库 > 架设用Webservice实现文件上传功能CentOS服务器(二)--WebService

架设用Webservice实现文件上传功能CentOS服务器(二)--WebService

功能概述,看代码中注释应该可以理解
  • 为了文件安全对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服务器(一)


架设用Webservice实现文件上传功能CentOS服务器(二)--WebService