1. 程式人生 > >基於spring boot ftp檔案上傳

基於spring boot ftp檔案上傳

對ftp檔案上傳將行封裝,實現連線的單例模式,完成執行緒安全的改進,ftp檔案上傳下載失敗的重試。

application.yml配置檔案

ftp:
   ip: 127.0.0.1
   port: 21
   username: admin
   password: admin
   downloadSleep: 100 #檔案下載失敗下次超時重試時間
   downloadRetry: 10 #檔案下載失敗重試次數
   uploadSleep: 100 #檔案上傳失敗下次超時重試時間
   uploadRettry: 10  #檔案上傳失敗重試次數

FTPClientUtils.java

包含ftp檔案上傳的一些基本方法,單個上傳,批量下載,單個檔案下載

/**
 * FTP檔案上傳下載工具類
 * @author 奇點_
 *
 */
@Component
@ConfigurationProperties(prefix = "ftp")
public class FTPClientUtils {
private static int downloadSleep;
private static int downloadRetry;
private static int uploadSleep;
private static int uploadRettry;
private static Logger LOGGER = LoggerFactory.getLogger(FTPClientUtils.class);
/**
 * 
 * @param ftpPath 上傳到ftp的路徑
 * @param file 上傳到ftp的檔案物件
 * @return boolean  true上傳檔案成功   false  上傳檔案失敗
 */
public static boolean doUpLoad(String ftpPath,File file){
boolean result=false;
Integer i = 0;
while(!result){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
try {
client.changeDirectory(ftpPath);


} catch (Exception e) {
LOGGER.error("ftp檔案目錄不存在:"+ftpPath);
}
client.upload(file);
if(i>0){
LOGGER.info("ftp重試檔案上傳成功,ftp路徑:"+ftpPath+",檔名稱:"+file.getName());
}else{
LOGGER.info("ftp檔案上傳成功,ftp路徑為"+ftpPath+",檔名稱:"+file.getName());
}
result = true;
}catch (Exception e) {
i++;
LOGGER.error("ftp檔案上傳失敗,重試中。。。第"+i+"次,錯誤資訊"+e.getMessage());
if(i>uploadRettry){
LOGGER.error("ftp檔案上傳失敗,超過重試次數結束重試,錯誤資訊"+e.getMessage());
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(uploadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
}


return result;
}

/**
 * 
 * @param ftpPath 要下載的檔案在ftp中的路徑
 * @param fileName 要下載的檔名稱
 * @param localPath 檔案要下載的路徑
 * @return false 下載失敗 true 下載成功
 */
    public static boolean doDownLoad(String ftpPath,String fileName,String localPath){
    boolean result=false;
        Integer i = 0;
        while(!result){
    FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {


client.changeDirectory(ftpPath);

    client.download(fileName, new File(localPath+"/"+fileName));
    if(i>0){
    LOGGER.info("ftp檔案重試下載成功,ftp地址:"+ftpPath+",檔名稱:"+fileName+"本地檔案地址:"+localPath);
    }else{
    
    LOGGER.info("ftp檔案下載成功,ftp地址:"+ftpPath+",檔名稱:"+fileName+"本地檔案地址:"+localPath);
    }
    result = true;
}catch (Exception e) {
i++;
LOGGER.error("ftp檔案下載失敗,重試中。。。第"+i+"次,錯誤資訊ftp地址:"+ftpPath+",檔名稱:"+fileName+"本地檔案地址:"+localPath+e.getMessage());
if(i>downloadRetry){
LOGGER.error("ftp檔案下載失敗,超過重試次數結束重試,錯誤資訊ftp地址:"+ftpPath+",檔名稱:"+fileName+"本地檔案地址:"+localPath+e.getMessage());
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(downloadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
        }
return result;

}


/**
 * 
 * @param ftpPath 下載該目錄下的所有檔案,不包括資料夾
 * @param localPath 下載到本地的目錄
 * @return true 下載成功  false 下載失敗
 */
public static boolean doDownLoad(String ftpPath,String localPath){
boolean result=false;
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {
    client.changeDirectory(ftpPath);


FTPFile[] fileNames = client.list();
for (FTPFile ftpFile : fileNames) {
if(ftpFile.getType()==FTPFile.TYPE_FILE){

try {
doDownLoad(ftpPath,ftpFile.getName(),localPath);
} catch (Exception e) {

}
}
}
result = true;
}catch (Exception e) {
LOGGER.error("ftp檔案批量下載失敗,錯誤資訊"+e.getMessage());
}
return result;

}

    
    /**  
     * 判斷一個FTP路徑是否存在,如果存在返回型別(FTPFile.TYPE_DIRECTORY=1、FTPFile.TYPE_FILE=0、FTPFile.TYPE_LINK=2)  
     * 如果檔案不存在,則返回一個-1  
     * @param ftpPath FTP檔案或資料夾路徑  
     * @return 存在時候返回型別值(檔案0,資料夾1,連結2),不存在則返回-1  
     */   
    public static int isExist(String ftpPath){
        FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
            FTPFile[] list = null;   
            try {   
                list = client.list(ftpPath);   
            } catch (Exception e) {   
                return -1;   
            }   
            if (list.length > 1) return FTPFile.TYPE_DIRECTORY;   
            else if (list.length == 1) {   
                FTPFile f = list[0];   
                if (f.getType() == FTPFile.TYPE_DIRECTORY) return FTPFile.TYPE_DIRECTORY;   
                String _path = ftpPath +File.separator+ f.getName();   
                try {   
                    int y = client.list(_path).length;   
                    if (y == 1) return FTPFile.TYPE_DIRECTORY;    
                    else return FTPFile.TYPE_FILE;   
                } catch (Exception e) {   
                    return  -1;   
                }   
            } else {   
                try {   
                    client.changeDirectory(ftpPath);   
                    return FTPFile.TYPE_DIRECTORY;   
                } catch (Exception e) {   
                        return -1;   
                }   
            }   
    }
    
    
    /**
 * 
 * @param ftpPath 遞迴下載該目錄下的所有檔案。
 * @param localPath 下載到本地的目錄
 * @return true 下載成功  false 下載失敗
 */
public synchronized static boolean doDownLoadAll(String ftpPath,String localPath){
boolean result=false;
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {

client.changeDirectory(ftpPath);

FTPFile[] fileNames = client.list();
for (FTPFile ftpFile : fileNames) {
if(ftpFile.getType()==FTPFile.TYPE_FILE){
try {
doDownLoad(ftpPath, localPath);
} catch (Exception e) {

}
}
if(ftpFile.getType()==FTPFile.TYPE_DIRECTORY){
String path = localPath+"/"+ftpFile.getName();
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
doDownLoadAll(ftpPath+"/"+ftpFile.getName(), path);
}
}
result = true;
}catch (Exception e) {

LOGGER.error("ftp檔案批量下載失敗,錯誤資訊"+e.getMessage());
}
return result;
}
    
    /**
     * 
     * @param ftpPath ftp的檔案路徑
     * @param localPath 檔案下載到的本地路徑
     * @param ftpPathBak 
     * @param isDeleteFile  下載後是否刪除檔案,傳入true or false
     * @param isBakFile
     * @return
     */
public static boolean doDownLoad(String ftpPath, String localPath, String ftpPathBak, String isDeleteFile, String isBakFile) {
boolean result=false;
Integer k = 0;
while(!result){
FTPClient client = FTPConnectionFactory.getInstance().makeConnection();
try {

client.changeDirectory(ftpPath);

String[] fileNames = client.listNames();
for (int i = 0; i < fileNames.length; i++) {
File file = new File(localPath+ fileNames[i]);
client.download(fileNames[i], file);
if (isBakFile.equals("true")){
client.rename(fileNames[i], ftpPathBak+fileNames[i]);
}
if (isDeleteFile.equals("true")){
client.deleteFile(fileNames[i]);
}
}
if(k>0){
    LOGGER.info("ftp檔案重試下載成功,ftp地址:"+ftpPath+",本地檔案地址:"+localPath);
    }else{
    LOGGER.info("ftp檔案下載成功,ftp地址:"+ftpPath+"本地檔案地址:"+localPath);
    }
result = true;
} catch (Exception e) {
k++;
LOGGER.error("ftp檔案下載失敗,重試中。。。第"+k+"次,錯誤資訊"+e.getMessage());
if(k>downloadRetry){
return result;
}
try {
TimeUnit.MILLISECONDS.sleep(downloadSleep);
} catch (InterruptedException e1) {
e1.printStackTrace();
}
}
 }
 return result;
     }


public static int getDownloadSleep() {
return downloadSleep;
}


public static void setDownloadSleep(int downloadSleep) {
FTPClientUtils.downloadSleep = downloadSleep;
}


public static int getDownloadRetry() {
return downloadRetry;
}


public static void setDownloadRetry(int downloadRetry) {
FTPClientUtils.downloadRetry = downloadRetry;
}


public static int getUploadSleep() {
return uploadSleep;
}


public static void setUploadSleep(int uploadSleep) {
FTPClientUtils.uploadSleep = uploadSleep;
}


public static int getUploadRettry() {
return uploadRettry;
}


public static void setUploadRettry(int uploadRettry) {
FTPClientUtils.uploadRettry = uploadRettry;
}

}

SFTPConnectionFactory.java

是生成sftp上傳物件的工場類

@Component
@ConfigurationProperties(prefix = "ftp")
public class FTPConnectionFactory {
private static Logger LOGGER = LoggerFactory.getLogger(FTPClientUtils.class);
/** FTP ip地址*/
private static String ip;
/** FTP 埠號*/
private static int port;
/** FTP 設定字符集*/
private static String charset;
/** FTP 使用者名稱*/
private static String username;
/** FTP 密碼*/
private static String password;


private static final FTPConnectionFactory factory = new FTPConnectionFactory();
private FTPClient client;
private FTPConnectionFactory(){

}

public static FTPConnectionFactory getInstance(){
return factory;
}
synchronized public FTPClient  makeConnection(){
if(client==null||!client.isConnected()){
try {
client = new FTPClient();
client.connect(ip, port);
client.setCharset(charset);
client.login(username, password);
} catch (Exception e) {
LOGGER.error("ftp登入失敗,檢測登入ip,埠號,使用者名稱密碼是否正確,錯誤資訊為"+e.getMessage());
}
LOGGER.info("ftp伺服器連線成功");
}
return client;
}
/**  
     * 關閉連線 server   
     */    
    public  void logout(){    
        if (client != null) {    
            if (client.isConnected()) {    
            try {
client.disconnect(false);
} catch (Exception e) {
LOGGER.error("ftp連線斷開失敗,錯誤資訊"+e.getMessage());
};    
            }    
        }    
          
    }
public static String getIp() {
return ip;
}


public static void setIp(String ip) {
FTPConnectionFactory.ip = ip;
}


public static int getPort() {
return port;
}


public static void setPort(int port) {
FTPConnectionFactory.port = port;
}


public static String getCharset() {
return charset;
}


public static void setCharset(String charset) {
FTPConnectionFactory.charset = charset;
}


public static String getUsername() {
return username;
}


public static void setUsername(String username) {
FTPConnectionFactory.username = username;
}


public static String getPassword() {
return password;
}


public static void setPassword(String password) {
FTPConnectionFactory.password = password;
}




}

pom.xml 依賴

 <dependencies>
    <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
    </dependency>
    <dependency>
        <groupId>fakepath</groupId>
        <artifactId>ftp4j</artifactId>
        <version>1.7.2</version>
   </dependency>
   <dependency>  
	    <groupId>com.jcraft</groupId>  
	    <artifactId>jsch</artifactId>  
	    <version>0.1.54</version>  
   </dependency>
   <dependency>  
    <groupId>org.springframework.boot</groupId>  
    <artifactId>spring-boot-configuration-processor</artifactId>  
    <optional>true</optional>  
   </dependency>  
  </dependencies>