Ftp Java工具類

jopen 10年前發布 | 97K 次閱讀 常用工具包 FTP

import java.io.BufferedInputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.UnsupportedEncodingException;
import java.net.SocketException;
import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.commons.lang.StringUtils; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply;

/**

  • FTP工具類,使用Apache的FTP組件實現 / public class FtpUtil {

private static final Log log = Log.getLog(FtpUtil.class); public static final int BINARY_FILE_TYPE = FTP.BINARY_FILE_TYPE; public static final int ASCII_FILE_TYPE = FTP.ASCII_FILE_TYPE; public static final String ISO_8859_1 = "ISO-8859-1";

public static final char FTP_PATH_CHAR = '/';

/*

* 方法download的作用:FTP下載
* 修改記錄: [20120504_904032_增加存儲路徑]
* @param ftpUrl 請求信息 格式:ftp://user:password@ip:port/path/fileName
* @param storePath 文件存儲路徑
* @param maxSize 文件大小,允許ftp下載遠程文件的最大值,單位為byte,超過此大小將不允許下載
* @return
* @throws Exception
* @Exception 異常對象
* @version  1.0[修改時小數點后+1]
*/

public static File download(String ftpUrl,String storePath, long maxSize) throws Exception {

FtpConfInfo infoConf = getInfo(ftpUrl);

   if (infoConf == null) {
       log.error("構建FTP配置信息失敗,請檢查:" + ftpUrl);
       return null;
   }
   FTPClient client = null;
   File file = null;
   try {
       client=connectServer(infoConf);
       if (client == null) {
           log.error("構建FTP客戶端失敗");
           return null;
       }

       log.debug("FTP服務器連接成功");

       if (infoConf.getLocation() != null) {
           String[] ss = infoConf.getLocation().split("/");
           for (String s : ss) {
               client.changeWorkingDirectory(s);
           }
       }
       log.debug("FTP切換目錄成功download()");

String fileName = downFile(infoConf ,storePath==null?"":storePath, client, infoConf.getFileName(), maxSize);

if (fileName == null) { return null; } file = new File(fileName); if (!file.isFile()) { log.error("下載的文件失敗"); return null; } log.debug("文件下載成功準備重命名,file = "+fileName); String suffix = infoConf.getFileName().substring(infoConf.getFileName().lastIndexOf('.')); File tempFile = new File(storePath+ File.separator +AssetIDUtil.getOnlyNumberForWebapp() + suffix); file.renameTo(tempFile);//重命名保持唯一性 file = tempFile; } catch (Exception e) { log.error("", e); throw e; } finally { // 關閉ftp closeServer(client); } return file; }

/**

* FTP批量下載文件到本地目錄
*
* @param localPath
*            本地目錄
* @param ftpUrlList
*            FTP文件列表
* @return localFilePathList 本地文件路徑列表
*/

public static List<String> downloadFiles(String localPath, List<String> ftpUrlList, long maxSize) throws Exception { List<String> localFilePathList = null; if (ftpUrlList != null && ftpUrlList.size() > 0) { localFilePathList = new ArrayList<String>(); FtpConfInfo infoConf = getInfo(ftpUrlList.get(0)); if (infoConf == null) { log.error("構建FTP配置信息失敗,請檢查:" + ftpUrlList.get(0)); return null; } FTPClient client = null; try { client = connectServer(infoConf); if (client == null) { log.error("構建FTP客戶端失敗"); return null; } for (String ftpUrl : ftpUrlList) { infoConf = getInfo(ftpUrl); if (infoConf.getLocation() != null) { String[] ss = infoConf.getLocation().split("/"); for (String s : ss) { client.changeWorkingDirectory(s); } } String fileName = downFile(infoConf ,localPath + File.separator

                       + infoConf.getLocation(), client, infoConf
                       .getFileName(), maxSize);
               if (fileName != null) {
                   localFilePathList.add(fileName);
               }
           }
       } catch (Exception e) {
           log.error("", e);
           throw e;
       } finally {
           // 關閉ftp
           closeServer(client);
       }
   }
   return localFilePathList;

}

/**

* 判斷是否有重名海報
*
* @param ftpUrl
* @param newName
* @return
* @throws Exception
*/

public static boolean checkName(String ftpUrl, String newName) throws Exception { FtpConfInfo infoConf = getInfo(ftpUrl); FTPClient ftpclient = null; if (infoConf.getLocation() != null) { ftpclient = connectServer(infoConf); String[] ss = infoConf.getLocation().split("/"); for (String s : ss) { if (!existDirectory(ftpclient, s)) { closeServer(ftpclient); return true; } ftpclient.changeWorkingDirectory(s); } } if (ftpclient == null) throw new Exception("FTP鏈接不成功,請檢查FTP鏈接參數!"); if(newName==null) throw new Exception("檢查重名方法的參數newName不允許為空!"); else newName = new String(newName.getBytes(infoConf.getEncoding()),FtpUtil.ISO_8859_1);

   FTPFile[] files = listFiles(ftpclient, newName);
   closeServer(ftpclient);

   if (files.length > 0)
   {
       return false;
   }
   else
   {
       return true;
   }

}

public static void clearPath(String ftpUrl, String newName) throws Exception { FtpConfInfo infoConf = getInfo(ftpUrl); FTPClient ftpclient = null; if (infoConf.getLocation() != null) { ftpclient = connectServer(infoConf); String[] ss = infoConf.getLocation().split("/"); for (String s : ss) { if (!existDirectory(ftpclient, s)) { closeServer(ftpclient); return; } ftpclient.changeWorkingDirectory(s); } } if (ftpclient == null) throw new Exception("FTP鏈接不成功,請檢查FTP鏈接參數!"); if(newName==null) throw new Exception("刪除文件方法的參數newName不允許為空!"); else newName = new String(newName.getBytes(infoConf.getEncoding()),FtpUtil.ISO_8859_1);

   FTPFile[] files = listFiles(ftpclient, null);

   for (FTPFile file : files) {
       if (file.isFile()) {
           if (!file.getName().equals(newName))
               ftpclient.deleteFile(file.getName());
       }
   }
   closeServer(ftpclient);

}

/**

* 上載文件到遠程FTP路徑中
*
* @param ftpUrl
*            eg: ftp://admin:admin@172.30.20.121:2121/poster/
* @param file
* @return [boolean] false=失敗;true=成功.
*/

public static boolean upload(String ftpUrl, File file, String newName) throws Exception { FtpConfInfo infoConf = getInfo(ftpUrl); if (infoConf == null) { log.error("構建FTP配置信息失敗,請檢查:" + ftpUrl); return false; } FTPClient ftpclient = connectServer(infoConf); if (ftpclient == null) { log.error("構建FTP客戶端失敗"); return false; } if(newName==null) throw new Exception("上傳文件方法的參數newName不允許為空!"); else newName = new String(newName.getBytes(infoConf.getEncoding()),FtpUtil.ISO_8859_1); if (infoConf.getLocation() != null) { String[] ss = infoConf.getLocation().split("/"); for (String s : ss) { if (!existDirectory(ftpclient, s)) ftpclient.mkd(s); ftpclient.changeWorkingDirectory(s); } } if (!file.exists()) { log.error("要上傳的文件不存在"); return false; } boolean storeResult = false; InputStream is = null; try { is = new FileInputStream(file); storeResult = ftpclient.storeFile(newName, is); if(!storeResult){ ftpclient.enterLocalPassiveMode(); storeResult = ftpclient.storeFile(newName, is); } log.debug("uploadFTP的當前目錄" + ftpclient.printWorkingDirectory()); ftpclient.logout(); closeServer(ftpclient); if (storeResult) log.info("文件傳輸到FTP成功"); else log.info("文件傳輸到FTP失敗"); return storeResult; } catch (Exception e) { log.error("", e); throw e; } finally { if (is != null) is.close(); } }

/**

* 刪除FTP上的文件
*
* @param ftpUrl
*            eg:ftp://admin:admin@172.30.20.121:2121/IsmpPicture/201006/
*            201006154100845_1083136_jpg
* @return 刪除海報失敗
* @throws Exception
*/

public static boolean delete(String ftpUrl) throws Exception { boolean deleteResult = false; FtpConfInfo infoConf = getInfo(ftpUrl); if (infoConf == null) { log.error("構建FTP配置信息失敗,請檢查:" + ftpUrl); return false; } FTPClient ftpclient = connectServer(infoConf); if (ftpclient == null) { log.error("構建FTP客戶端失敗"); return false; } if (infoConf.getFileName() != null) { if (infoConf.getLocation() != null) { deleteResult = ftpclient.deleteFile(infoConf.getLocation()

                   + "/" + infoConf.getFileName());
       } else {
           deleteResult = ftpclient.deleteFile(infoConf.getFileName());
       }
   }
   ftpclient.logout();
   closeServer(ftpclient);
   return deleteResult;

}

/**

* 獲得FTP對象信息
*
* @param ftpInfo
* @return FtpConfInfo
*/

private static FtpConfInfo getInfo(String ftpInfo) { if (ftpInfo == null) { return null; }

String regEx = "^ftp://([\w]+:[\S]@)?[\S]+/[^\/:?\"<>|]*$";
Pattern p = Pattern.compile(regEx); Matcher m = p.matcher(ftpInfo); if (!m.find()) { return null; }

String str = ftpInfo.substring("ftp://".length()); String serverInfo = str.substring(0, str.indexOf("/")); String fileName = str.substring(str.indexOf("/") + 1); // if path exist String path = null; if (fileName.indexOf("/") > -1) { path = fileName.substring(0, fileName.lastIndexOf("/")); fileName = fileName.substring(fileName.lastIndexOf("/") + 1); }

   //解析ftp用戶名、密碼、IP、端口號 特別是密碼含有特殊字符的如: "icdspics:ic:ds!@#@125.210.227.11:98"(lidahu)
   int k = serverInfo.indexOf(":");
   String serverName =serverInfo.substring(0,k) ;
   String server = serverInfo.substring(k+1);
   int j = server.lastIndexOf("@");
   String serverPwd = server.substring(0,j);

   String serverIpPort = server.substring(j+1);
   int i = serverIpPort.indexOf(":");
   String serverIp = null;
   String serverPort = null;
   if(i==-1){
       serverIp = serverIpPort;
   }
   else{
       serverIp =  serverIpPort.substring(0,i);
       serverPort= serverIpPort.substring(i+1);
   }
   FtpConfInfo conf = new FtpConfInfo();

conf.setUser(serverName); conf.setPassword(serverPwd); conf.setServer(serverIp); conf.setLocation(path); conf.setFileName(fileName); conf.setMaxWorkTime(60*1000l);//默認60秒完成 if (StringUtils.isNotEmpty(serverPort)) { try { conf.setPort(Integer.parseInt(serverPort)); } catch (ClassCastException e) { // 設置默認端口 21 conf.setPort(21); }

} else { // 設置默認端口 21 conf.setPort(21); }

return conf;

}

/**

* Check the path is exist; exist return true, else false.
*
* @param ftpClient
* @param path
* @return
* @throws IOException
*/

private static boolean existDirectory(FTPClient ftpClient, String path) throws IOException {
boolean flag = false; FTPFile[] listFiles; try { String Localpath = ftpClient.printWorkingDirectory(); log.debug(Localpath); listFiles = listFiles(ftpClient, null); } catch (Exception e) { log.error("檢查FTP路徑發送錯誤",e); return false; } if(listFiles == null)return false; for(FTPFile ffile :listFiles){ boolean isFile = ffile.isFile(); if(!isFile){ if(ffile.getName().equalsIgnoreCase(path)){ flag = true; break; } } } return flag; }

/**

* (私有方法)連接FTP,返回FTPClient連接[返回根目錄],使用完連接后,調用closeServer關閉連接
*
* @param conf
* @return FTPClient
* @throws SocketException
* @throws IOException
*/

private static FTPClient connectServer(FtpConfInfo conf) throws SocketException, IOException { FTPClient ftpClient = new FTPClient(); ftpClient.setConnectTimeout(5000);//超時設置,建議采用配置 ftpClient.setDataTimeout(10*1000);//設置數據響應超時時間默認10秒

try { ftpClient.connect(conf.getServer(), conf.getPort()); } catch (SocketException e ) { log.error("海報FTP服務器連接超時,請檢查FTP服務器地址及端口配置是否正確:FTPServer[" + conf.getServer() + "]--Port[" + conf.getPort() + "]",e); throw e; } catch (IOException e ) { log.error("海報FTP服務器連接超時,請檢查FTP服務器地址及端口配置是否正確:FTPServer[" + conf.getServer() + "]--Port[" + conf.getPort() + "]",e); throw e; }

if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {

       if (ftpClient.login(conf.getUser(), conf.getPassword())) {
           ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
           /** 解決中文問題的解碼 903889 2010-12-30 Start **/
           ftpClient.sendCommand("FEAT");
           String featRS = ftpClient.getReplyString();
           String encoding = "GBK";
           if(featRS.indexOf(" UTF8")!=-1)encoding="UTF8";
           if(conf.getLocation()!=null)
               conf.setLocation(new String(conf.getLocation().getBytes(encoding),FtpUtil.ISO_8859_1));
           if(conf.getFileName()!=null)
               conf.setFileName(new String(conf.getFileName().getBytes(encoding),FtpUtil.ISO_8859_1));
           conf.setEncoding(encoding);//將獲取的編碼信息帶出來

           ftpClient.setActivePortRange(9000, 9100);//主動模式下設置客戶方端口范圍9000-9100              

// ftpClient.enterLocalPassiveMode();//將默認的PORT主動模式改成PASV被動模式 / 解決中文問題的解碼 End / return ftpClient; } closeServer(ftpClient); log.error("FTP的用戶名和密碼不對"); log.error(conf.toString()); return null; } closeServer(ftpClient); log.error("FTP的連接失敗"); log.error(conf.toString()); return null; }

/**

* (私有方法)關閉FTP連接
*
* @param ftpClient
* @throws IOException
*/

private static void closeServer(FTPClient ftpClient) throws IOException { if (ftpClient != null && ftpClient.isConnected()) { ftpClient.disconnect(); } }

/**

* 取得ftp文件
* @param ftp
* @param fileName
* @return
* @throws IOException
*/

private static FTPFile[] listFiles(FTPClient ftp, String fileName) throws IOException { FTPFile[] files = null; if (StringUtils.isNotEmpty(fileName)) { files = ftp.listFiles(fileName); if (files.length != 1) { // 如果沒有不能下載文件,再用被動模式試一次(lidahu) ftp.enterLocalPassiveMode(); files = ftp.listFiles(fileName); } } else { files = ftp.listFiles(); // 以被動模式再試一次 if (files.length == 0 || files == null) { ftp.enterLocalPassiveMode(); files = ftp.listFiles(); } } return files; }

/**

* (私有方法) 下載文件
*
* @param ftp
* @param fileName
* @param maxSize
*            為-1不檢查文件大小
* @return String
* @throws UnsupportedEncodingException
* @throws IOException
*/

private static String downFile(FtpConfInfo ftpConfInfo ,String path, FTPClient ftp, String fileName, long maxSize) throws UnsupportedEncodingException, IOException, Exception { if (ftp == null || fileName == null || fileName.length() < 1) { log.error("文件名為空或不存在"); return null; }

   FTPFile[] files = listFiles(ftp,fileName);
   if(files.length != 1){
       log.error("PATH:" + path + "|FileName:" + fileName + "當前文件不存在或有多個,實際文件個數為:" + files.length);
       return null;
   }

   FTPFile file = files[0];
   if(!file.isFile()){
       log.error(file.getName() + "不是文件!");
       return null;
   }
   long lRemoteSize = file.getSize();

// if (lRemoteSize > maxSize && maxSize != -1) { // log.error("要下載的文件太大,超過maxSize=" + maxSize + "chars"); // return null; // } long maxTime = lRemoteSize/1024/50;//50K一秒, ftpConfInfo.setMaxWorkTime(maxTime*1000);

   if (path == null || path.equals("")) {
       String temp = System.getProperty("user.dir");
       path = temp;
   }
   File f = new File(path);
   if (!f.exists()) {
       boolean mkResult = f.mkdirs();
       if(!mkResult)log.warn("make dir failed");
   }
   path = path + File.separator + fileName;


   try
   {
       File localFile = new File(path);
       OutputStream output = new FileOutputStream(localFile);
       ftp.retrieveFile(fileName, output);
       output.close();
   }
   catch (Exception e)
   {
       log.error("下載文件"+path+"失敗", e);
       throw new Exception("FTP傳輸失敗,中斷連接");
   }
   finally
   {
       FtpUtil.closeServer(ftp);
   }


   /*

   RFS rfs = new RFS(ftpConfInfo,ftp,path,fileName);
   rfs.setName("FtpRFS Thread");
   rfs.start();
   int forInt = 1;
   long oldfilesize = 0;      
   while(forInt < 20){
       Thread.sleep(200l);
       if(rfs.count >= lRemoteSize)break;//傳輸完畢,退出.兼容服務器的文件增大情況,不保證增大時完整性
       if(rfs.count == oldfilesize){   //相當的時候,增加計數器2秒,則開始中斷          
           forInt++;              
       }  
       oldfilesize = rfs.count;//每次處理后,賦值供下次比較
   }

if(forInt == 20 ){ //存在FTP傳輸2秒無響應,中斷連接 log.error("FTP傳輸2秒無響應,中斷連接");
rfs.myInterrupt(); throw new Exception("FTP傳輸2秒無響應,中斷連接"); } log.debug(System.currentTimeMillis()+" "+rfs.toString()+ "="+rfs.getState().toString()); if(rfs.getState()!=Thread.State.TERMINATED){//RFS還存活時,中斷
Thread.sleep(100l); rfs.myInterrupt(); } */

   return path;

}

public static String repairFtpString(String ftpString) { if(StringUtils.isNotEmpty(ftpString) && FTP_PATH_CHAR != ftpString.charAt(ftpString.length()-1)) { return ftpString+FTP_PATH_CHAR; } else { return ftpString; } }

static class RFS extends Thread{ private FTPClient ftp = null; volatile long count = 0; private String path = null; private String fileName = null; private FtpConfInfo ftpConfInfo =null;

   RFS(FtpConfInfo ftpConfInfo,FTPClient ftp,String path,String fileName){
       this.ftp = ftp;
       this.path = path;
       this.ftpConfInfo =ftpConfInfo;
       this.fileName = fileName;
   }

   public void myInterrupt() throws IOException{          
       Thread.currentThread().interrupt();        
       FtpUtil.closeServer(ftp);

}

   private void copy(FtpConfInfo ftpConfInfo ,InputStream is ,OutputStream os) throws IOException, Exception{
       long timeA = System.currentTimeMillis();

// final StringBuffer timeout = new StringBuffer(); // if (ftpConfInfo!=null&&ftpConfInfo.getMaxWorkTime() > 0) { // final Timer timer = new Timer(); // timer.schedule(new TimerTask() { // public void run() { // timeout.append(true); // timer.cancel(); // } // }, ftpConfInfo.getMaxWorkTime()); // } byte[] buffer = new byte[1024]; count = 0; int n = 0; while (-1 != (n = is.read(buffer))) { // if ("true".equals(timeout.toString())) { // log.error("FTP數據傳輸時間超時!"); // throw new Exception("FTP數據傳輸時間超時!"); // } os.write(buffer, 0, n); count += n;
} long copyTime = (System.currentTimeMillis()-timeA); if(copyTime<1){ copyTime = 1; } log.debug("傳輸速率為(byte/毫秒):" + (count/copyTime)+"傳輸時間(毫秒)"+copyTime);
}

   public void run(){
       InputStream stO = null;
       OutputStream stD = null;
       try {          
           stO = new BufferedInputStream(ftp.retrieveFileStream(fileName));
           stD = new FileOutputStream(path);                
           log.debug("準備從FTP拷貝文件");
           copy(ftpConfInfo,stO,stD);
           stD.flush();
           log.debug("文件拷貝完成");
           ftp.completePendingCommand();
       } catch (Exception e) {
           log.error("文件傳輸異常", e);
       } finally {
           if (stO != null) {
               try {
                   stO.close();
               } catch (IOException e) {
                   log.error("FTP關閉輸入流異常", e);
               }
           }
           if (stD != null) {
               try {
                   stD.flush();
                   stD.close();
               } catch (IOException e) {                          
                   log.error("FTP關閉輸出流異常", e);
               }

           }
           stO = null;
           stD = null;
       }
   }

}

}</pre>

 本文由用戶 jopen 自行上傳分享,僅供網友學習交流。所有權歸原作者,若您的權利被侵害,請聯系管理員。
 轉載本站原創文章,請注明出處,并保留原始鏈接、圖片水印。
 本站是一個以用戶分享為主的開源技術平臺,歡迎各類分享!