Java使用FTPClient鏈接文件服務器並作相應操做(代碼)

/**
 * 
 */
package com.common.file;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.log4j.Logger;

import com.common.DateUtils;

/**
 * FTP客戶端工具類
 * @author luolin
 *
 * @version $id:FTPClientUtils.java,v 0.1 2015年11月13日 下午4:18:07 luolin Exp $
 */
public class FTPClientUtil {

    private static final Logger LOGGER = Logger.getLogger(FTPClientUtil.class);

    /**
     * 鏈接文件服務器
     * @param addr 文件服務器地址
     * @param port 端口
     * @param username 用戶名
     * @param password 密碼
     * @throws Exception 
     */
    public static FTPClient connect(String addr, int port, String username, String password) {
        LOGGER.info("【鏈接文件服務器】addr = " + addr + " , port : " + port + " , username = " + username + " , password = "
                    + password);

        FTPClient ftpClient = new FTPClient();
        try {
            // 鏈接
            ftpClient.connect(addr, port);
            // 登陸
            ftpClient.login(username, password);
            // 被動模式:每次數據鏈接以前,ftp client告訴ftp server開通一個端口來傳輸數據(參考資料:FTP主動/被動模式的解釋)
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        } catch (Exception e) {
            LOGGER.error("【鏈接文件服務器失敗】", e);
            throw new RuntimeException("鏈接文件服務器失敗");
        }
        // 判斷文件服務器是否可用??
        if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            closeConnection(ftpClient);
        }
        return ftpClient;
    }

    /**
     * 鏈接文件服務器
     * @param addr 文件服務器地址
     * @param port 端口
     * @param username 用戶名
     * @param password 密碼
     * @param workingDirectory 目標鏈接工做目錄
     * @throws Exception 
     */
    public static FTPClient connect(String addr, int port, String username, String password, String workingDirectory)
                                                                                                                     throws Exception {
        FTPClient ftpClient = connect(addr, port, username, password);
        changeWorkingDirectory(workingDirectory, ftpClient);
        return ftpClient;
    }

    /**
     * 關閉鏈接,使用完鏈接以後,必定要關閉鏈接,不然服務器會拋出 Connection reset by peer的錯誤
     * @throws IOException
     */
    public static void closeConnection(FTPClient ftpClient) {
        LOGGER.info("【關閉文件服務器鏈接】");
        if (ftpClient == null) {
            return;
        }

        try {
            ftpClient.disconnect();
        } catch (IOException e) {
            LOGGER.error("【關閉鏈接失敗】", e);
            throw new RuntimeException("關閉鏈接失敗");
        }
    }

    /**
     * 切換工做目錄
     * @param directory 目標工做目錄
     * @param ftpClient 
     * @throws IOException
     */
    public static void changeWorkingDirectory(String directory, FTPClient ftpClient) {
        LOGGER.info("【切換工做目錄】directory : " + directory);
        baseValidate(ftpClient);
        // 切換到目標工做目錄
        try {
            if (!ftpClient.changeWorkingDirectory(directory)) {
                ftpClient.makeDirectory(directory);
                ftpClient.changeWorkingDirectory(directory);
            }
        } catch (Throwable e) {
            LOGGER.error("【切換工做目錄失敗】", e);
            throw new RuntimeException("切換工做目錄失敗");
        }
    }

    /** 
     * 上傳文件/文件夾
     * @param file 上傳的文件或文件夾 
     * @return 文件存放的路徑以及文件名
     * @throws Exception 
     */
    public static void upload(File file, FTPClient ftpClient) throws Exception {
        if (file == null) {
            LOGGER.warn("【存儲的文件爲空】");
            throw new RuntimeException("上傳文件爲空");
        }
        LOGGER.info("【上傳文件/文件夾】file : " + file.getName());
        baseValidate(ftpClient);
        // 是文件,直接上傳
        if (!file.isDirectory()) {
            storeFile(new File(file.getPath()), ftpClient);
            return;
        }

        changeWorkingDirectory(file.getName(), ftpClient);
        // 文件夾,遞歸上傳全部文件
        for (File item : file.listFiles()) {
            if (!item.isDirectory()) {
                storeFile(item, ftpClient);
                continue;
            }
            upload(item, ftpClient);
            ftpClient.changeToParentDirectory();
        }
    }

    /**
     * 刪除文件
     * @param fileName 要刪除的文件地址
     * @return true/false
     * @throws IOException 
     */
    public static boolean delete(String fileName, FTPClient ftpClient) throws IOException {
        LOGGER.info("【刪除文件】fileName : " + fileName);
        baseValidate(ftpClient);
        if (StringUtils.isBlank(fileName)) {
            LOGGER.warn("【參數fileName爲空】");
            throw new NullArgumentException("fileName");
        }
        return ftpClient.deleteFile(fileName);
    }

    /**
     * 存儲文件
     * @param file {@link File}
     * @throws Exception
     */
    public static void storeFile(File file, FTPClient ftpClient) throws Exception {
        if (file == null) {
            LOGGER.warn("【存儲的文件爲空】");
            throw new RuntimeException("存儲的文件爲空");
        }
        LOGGER.info("【存儲文件】file : " + file.getName());
        baseValidate(ftpClient);

        FileInputStream input = new FileInputStream(file);
        ftpClient.storeFile(file.getName(), input);
        input.close();
    }

    /**
     * 存儲文件
     * @param inputStream {@link InputStream}
     * @param fileName 文件名
     * @throws Exception
     */
    public static void storeFile(InputStream inputStream, String fileName, FTPClient ftpClient) throws Exception {
        LOGGER.info("【存儲文件】fileName = " + fileName);
        if (inputStream == null) {
            LOGGER.warn("【參數inputStream爲空】");
            throw new RuntimeException("存儲的文件爲空");
        }
        baseValidate(ftpClient);
        ftpClient.storeFile(fileName, inputStream);
        inputStream.close();
    }

    /**
     * 下載文件到指定目錄
     * @param ftpFile 文件服務器上的文件地址
     * @param dstFile 輸出文件的路徑和名稱
     * @throws Exception 
     */
    public static void downLoad(String ftpFile, String dstFile, FTPClient ftpClient) throws Exception {
        LOGGER.info("【下載文件到指定目錄】ftpFile = " + ftpFile + " , dstFile = " + dstFile);
        if (StringUtils.isBlank(ftpFile)) {
            LOGGER.warn("【參數ftpFile爲空】");
            throw new RuntimeException("【參數ftpFile爲空】");
        }
        if (StringUtils.isBlank(dstFile)) {
            LOGGER.warn("【參數dstFile爲空】");
            throw new RuntimeException("【參數dstFile爲空】");
        }
        baseValidate(ftpClient);
        File file = new File(dstFile);
        FileOutputStream fos = new FileOutputStream(file);
        ftpClient.retrieveFile(ftpFile, fos);
        fos.flush();
        fos.close();
    }

    /**
     * 從文件服務器獲取文件流
     * @param ftpFile 文件服務器上的文件地址
     * @return {@link InputStream}
     * @throws IOException
     */
    public static InputStream retrieveFileStream(String ftpFile, FTPClient ftpClient) throws IOException {
        LOGGER.info("【從文件服務器獲取文件流】ftpFile : " + ftpFile);
        if (StringUtils.isBlank(ftpFile)) {
            LOGGER.warn("【參數ftpFile爲空】");
            throw new RuntimeException("【參數ftpFile爲空】");
        }
        baseValidate(ftpClient);
        return ftpClient.retrieveFileStream(ftpFile);
    }

    /**
     * 複製文件
     * @param ftpClient {@link FTPClient}
     * @param sourceFile 源文件
     * @param targetDir 目標文件夾
     * @return 複製後的文件路徑及文件名
     * @throws Exception
     */
    public static String copy(FTPClient ftpClient, String sourceFile, String targetDir) throws Exception {
        return copy(ftpClient, sourceFile, targetDir, FileUtil.getFileNameNoPath(sourceFile));
    }

    /**
     * 複製文件
     * @param ftpClient {@link FTPClient}
     * @param sourceFile 源文件
     * @param targetDir 目標文件夾
     * @param newName 新的文件名
     * @return 複製後的文件路徑及文件名
     * @throws Exception
     */
    public static String copy(FTPClient ftpClient, String sourceFile, String targetDir, String newName)
                                                                                                       throws Exception {
        LOGGER.info("【拷貝文件】sourceFile = " + sourceFile + " , targetDir = " + targetDir + " , newName = " + newName);
        if (StringUtils.isBlank(sourceFile)) {
            LOGGER.warn("【參數sourceFile爲空】");
            throw new NullArgumentException("sourceFile");
        }
        if (StringUtils.isBlank(targetDir)) {
            LOGGER.warn("【參數targetDir爲空】");
            throw new NullArgumentException("targetDir");
        }
        if (StringUtils.isBlank(newName)) {
            LOGGER.warn("【參數newName爲空】");
            throw new NullArgumentException("newName");
        }
        baseValidate(ftpClient);
        LOGGER.info("【從文件服務器讀取源文件到輸入流中】");
        InputStream is = ftpClient.retrieveFileStream(sourceFile);
        // 主動調用一次getReply()把接下來的226消費掉. 這樣作是能夠解決這個返回null問題  
        ftpClient.getReply();
        if (is == null) {
            LOGGER.warn("【未找到源文件】");
            throw new RuntimeException("未找到源文件");
        }
        LOGGER.info("【將輸入流存儲到指定的目錄】");
        changeWorkingDirectory(targetDir, ftpClient);
        changeWorkingDirectory(DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER), ftpClient);
        storeFile(is, newName, ftpClient);

        return ftpClient.printWorkingDirectory() + File.separator + newName;
    }

    /**
     * 基本校驗
     * @param ftpClient {@link FTPClient}
     */
    private static void baseValidate(FTPClient ftpClient) {
        if (ftpClient == null) {
            LOGGER.warn("【參數ftpClient爲空】");
            throw new NullArgumentException("ftpClient");
        }
    }
}

FTPManager.java代碼:java

/**
 * 
 */
package com.common.file;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;

import javax.annotation.Resource;

import org.apache.commons.lang.NullArgumentException;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.log4j.Logger;
import org.springframework.stereotype.Component;

import com.common.DateUtils;
import com.common.property.FileSystemProperties;

/**
 * FTP文件管理器
 * @author luolin
 *
 * @version $id:FTPManager.java,v 0.1 2015年11月16日 上午11:08:13 luolin Exp $
 */
@Component("ftpManager")
public class FTPManager {

    private static final Logger  LOGGER = Logger.getLogger(FTPManager.class);
    /** file.system.properties文件內容映射類 */
    @Resource(name = "fileSystemProperties")
    private FileSystemProperties fileSystemProperties;

    /**
     * 上傳文件到FTP服務器
     * @param file {@link File}
     * @return 文件上傳到服務器的地址
     */
    public String upload(File file) {
        LOGGER.info("【上傳文件到FTP服務器】");
        if (file == null) {
            LOGGER.warn("【參數file爲空】");
            throw new NullArgumentException("file");
        }

        FTPClient ftpClient = connectServer(fileSystemProperties.getProjectWorkingDirectory());
        // 切換到子目錄,按日期,天天建立一個目錄
        String subFolder = DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER);
        FTPClientUtil.changeWorkingDirectory(subFolder, ftpClient);
        try {
            FTPClientUtil.upload(file, ftpClient);
        } catch (Exception e) {
            LOGGER.error("【文件上傳失敗】", e);
            throw new RuntimeException("文件上傳失敗");
        } finally {
            FTPClientUtil.closeConnection(ftpClient);
        }
        String uploadedFilePath = fileSystemProperties.getProjectWorkingDirectory() + File.separator + subFolder
                                  + File.separator + file.getName();
        LOGGER.info("【文件上傳完成】uploadedFilePath = " + uploadedFilePath);
        return uploadedFilePath;
    }

    /**
     * 上傳文件到FTP服務器
     * @param file {@link File}
     * @param targetFolder 目標子目錄
     * @return 文件上傳到服務器的地址
     */
    public String upload(File file, String targetFolder) {
        LOGGER.info("【上傳文件到FTP服務器】targetFolder : " + targetFolder);
        if (file == null) {
            LOGGER.warn("【參數file爲空】");
            throw new NullArgumentException("file");
        }

        FTPClient ftpClient = connectServer(fileSystemProperties.getProjectWorkingDirectory());
        // 切換到子目錄,按日期,天天建立一個目錄
        String subFolder = DateUtils.getNow(DateUtils.FORMAT_SHORT_FOLDER);
        FTPClientUtil.changeWorkingDirectory(targetFolder, ftpClient);
        FTPClientUtil.changeWorkingDirectory(subFolder, ftpClient);
        try {
            FTPClientUtil.upload(file, ftpClient);
        } catch (Exception e) {
            LOGGER.error("【文件上傳失敗】", e);
            throw new RuntimeException("文件上傳失敗");
        } finally {
            FTPClientUtil.closeConnection(ftpClient);
        }
        String uploadedFilePath = fileSystemProperties.getProjectWorkingDirectory() + File.separator + targetFolder
                                  + File.separator + subFolder + File.separator + file.getName();
        LOGGER.info("【文件上傳完成】uploadedFilePath = " + uploadedFilePath);
        return uploadedFilePath;
    }

    /**
     * 鏈接服務器
     * @return {@link FTPClient}
     */
    private FTPClient connectServer(String workingDirectory) {
        FTPClient ftpClient = null;
        try {
            // 鏈接服務器,並切換到對應的項目文件存儲目錄
            ftpClient = FTPClientUtil.connect(fileSystemProperties.getHost(), fileSystemProperties.getPort(),
                fileSystemProperties.getUsername(), fileSystemProperties.getPwd(), workingDirectory);
        } catch (Exception e) {
            LOGGER.error("【鏈接服務器失敗】", e);
            throw new RuntimeException("鏈接服務器失敗");
        }
        return ftpClient;
    }

    /**
     * 鏈接服務器
     * @return {@link FTPClient}
     */
    private FTPClient connectServer() {
        FTPClient ftpClient = null;
        try {
            // 鏈接服務器,並切換到對應的項目文件存儲目錄
            ftpClient = FTPClientUtil.connect(fileSystemProperties.getHost(), fileSystemProperties.getPort(),
                fileSystemProperties.getUsername(), fileSystemProperties.getPwd());
        } catch (Exception e) {
            LOGGER.error("【鏈接服務器失敗】", e);
            throw new RuntimeException("鏈接服務器失敗");
        }
        return ftpClient;
    }

    /**
     * 從服務器獲取文件輸入流
     * @param fileName 文件路徑和名稱
     * @return {@link InputStream}
     */
    public InputStream getFileInputStream(String fileName) {
        LOGGER.info("【從服務器獲取文件輸入流】fileName = " + fileName);
        if (StringUtils.isBlank(fileName)) {
            LOGGER.warn("【參數fileName爲空】");
            throw new NullArgumentException("fileName");
        }
        FTPClient ftpClient = connectServer();
        try {
            return FTPClientUtil.retrieveFileStream(fileName, ftpClient);
        } catch (IOException e) {
            LOGGER.error("【獲取文件流失敗】", e);
            throw new RuntimeException("獲取文件流失敗");
        } finally {
            FTPClientUtil.closeConnection(ftpClient);
        }
    }

    /**
     * 從文件服務器文件下載到應用服務器本地
     * @param fileName 文件路徑及名稱
     * @param tmpPath 臨時文件存放目錄
     * @return 存儲到臨時文件目錄的完整路徑
     */
    public String downloadFileToLocal(String fileName, String tmpPath) {
        LOGGER.info("【從文件服務器文件下載到應用服務器本地】fileName = " + fileName);
        if (StringUtils.isBlank(fileName)) {
            LOGGER.warn("【參數fileName爲空】");
            throw new NullArgumentException("fileName");
        }
        FTPClient ftpClient = connectServer();
        String name = FileUtil.getFileNameNoPath(fileName);
        try {
            FTPClientUtil.downLoad(fileName, tmpPath + File.separator + name, ftpClient);
        } catch (Exception e) {
            LOGGER.error("【下載文件失敗】", e);
            throw new RuntimeException("下載文件失敗");
        } finally {
            FTPClientUtil.closeConnection(ftpClient);
        }
        return tmpPath + File.separator + name;
    }

    /**
     * 刪除文件服務器的文件
     * @param fileName 文件在文件服務器的地址
     * @throws IOException
     */
    public void delete(String fileName) throws IOException {
        LOGGER.info("【刪除文件服務器的文件】fileName = " + fileName);
        FTPClientUtil.delete(fileName, connectServer());
    }

    /**
     * 文件拷貝
     * @param sourceFile 源文件地址
     * @param targetDir 目標文件夾
     * @return 文件拷貝後的完整路徑
     */
    public String copy(String sourceFile, String targetDir) {
        LOGGER.info("【文件拷貝】sourceFile = " + sourceFile + " , targetDir = " + targetDir);
        if (StringUtils.isBlank(sourceFile)) {
            LOGGER.warn("【參數sourceFile爲空】");
            throw new NullArgumentException("sourceFile");
        }
        if (StringUtils.isBlank(targetDir)) {
            LOGGER.warn("【參數targetDir爲空】");
            throw new NullArgumentException("targetDir");
        }
        try {
            return FTPClientUtil.copy(connectServer(), sourceFile, fileSystemProperties.getProjectWorkingDirectory()
                                                                   + File.separator + targetDir);
        } catch (Exception e) {
            LOGGER.error("【文件拷貝失敗】", e);
            throw new RuntimeException("文件拷貝失敗");
        }
    }
}

下面也給出我測試的時候,寫的demo的代碼spring

/**
 * 
 */
package com.eay.ftp;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;

import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;

/**
 * FTP客戶端工具類示例
 * @author ll
 *
 * @version $id:FTPClientExample.java,v 0.1 2015年11月13日 上午11:32:24 ll Exp $
 */
public class FTPClientExample {

    /** FTP客戶端實例 */
    private FTPClient ftpClient;

    /**
     * 私有構造器
     */
    private FTPClientExample() {
    }

    /**
     * 內部類維護單例,防止併發問題
     * @author luolin
     *
     * @version $id:FTPClientExample.java,v 0.1 2015年11月13日 下午2:34:08 luolin Exp $
     */
    private static class SingletonFactory {
        private static FTPClientExample instance = new FTPClientExample();
    }

    /**
     * 獲取實例
     * @return {@link FTPClientExample}
     */
    public static FTPClientExample getInstance() {
        return SingletonFactory.instance;
    }

    /**
     * 鏈接文件服務器
     * @param addr 文件服務器地址
     * @param port 端口
     * @param username 用戶名
     * @param password 密碼
     * @throws Exception 
     */
    public void connect(String addr, int port, String username, String password) throws Exception {
        ftpClient = new FTPClient();
        // 鏈接
        ftpClient.connect(addr, port);
        // 登陸
        ftpClient.login(username, password);
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        // 判斷文件服務器是否可用??
        if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            ftpClient.disconnect();
        }
    }

    /**
     * 鏈接文件服務器
     * @param addr 文件服務器地址
     * @param port 端口
     * @param username 用戶名
     * @param password 密碼
     * @param workingDirectory 目標鏈接工做目錄
     * @throws Exception 
     */
    public void connect(String addr, int port, String username, String password, String workingDirectory)
                                                                                                         throws Exception {
        ftpClient = new FTPClient();
        // 鏈接
        ftpClient.connect(addr, port);
        // 登陸
        ftpClient.login(username, password);
        ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
        // 判斷文件服務器是否可用??
        if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            ftpClient.disconnect();
        }
        changeWorkingDirectory(workingDirectory);
    }

    /**
     * 關閉鏈接,使用完鏈接以後,必定要關閉鏈接,不然服務器會拋出 Connection reset by peer的錯誤
     * @throws IOException
     */
    public void closeConnection() throws IOException {
        ftpClient.disconnect();
    }

    /**
     * 切換工做目錄
     * @param directory 目標工做目錄
     * @throws IOException
     */
    public void changeWorkingDirectory(String directory) throws IOException {
        // 切換到目標工做目錄
        if (!ftpClient.changeWorkingDirectory(directory)) {
            ftpClient.makeDirectory(directory);
            ftpClient.changeWorkingDirectory(directory);
        }
    }

    /** 
     * @param file 上傳的文件或文件夾 
     * @throws Exception 
     */
    public void upload(File file) throws Exception {

        if (file == null) {
            throw new RuntimeException("上傳文件爲空");
        }
        // 是文件,直接上傳
        if (!file.isDirectory()) {
            storeFile(new File(file.getPath()));
            return;
        }

        ftpClient.makeDirectory(file.getName());
        ftpClient.changeWorkingDirectory(file.getName());
        // 文件夾,遞歸上傳全部文件
        for (File item : file.listFiles()) {
            if (!item.isDirectory()) {
                storeFile(item);
                continue;
            }
            upload(item);
            ftpClient.changeToParentDirectory();
        }
    }

    /**
     * 刪除文件
     * @param fileName 要刪除的文件地址
     * @return true/false
     * @throws Exception
     */
    public boolean delete(String fileName) throws Exception {
        return ftpClient.deleteFile(fileName);
    }

    /**
     * 存儲文件
     * @param file {@link File}
     * @throws Exception
     */
    private void storeFile(File file) throws Exception {
        FileInputStream input = new FileInputStream(file);
        ftpClient.storeFile(file.getName(), input);
        input.close();
    }

    /**
     * 下載文件
     * @param ftpFile 文件服務器上的文件地址
     * @param dstFile 輸出文件的路徑和名稱
     * @throws Exception 
     */
    public void downLoad(String ftpFile, String dstFile) throws Exception {
        File file = new File(dstFile);
        FileOutputStream fos = new FileOutputStream(file);
        ftpClient.retrieveFile(ftpFile, fos);
        fos.flush();
        fos.close();
    }

    /**
     * 從文件服務器獲取文件流
     * @param ftpFile 文件服務器上的文件地址
     * @return {@link InputStream}
     * @throws IOException
     */
    public InputStream retrieveFileStream(String ftpFile) throws IOException {
        return ftpClient.retrieveFileStream(ftpFile);
    }

    public static void main(String[] args) throws Exception {
        FTPClientExample emp = FTPClientExample.getInstance();
        String addr = "192.168.111.60";
        int port = 21;
        String username = "admin";
        String password = "admin";
        emp.connect(addr, port, username, password);

        // 上傳文件
        emp.changeWorkingDirectory("bss");
        emp.upload(new File("E:\\example.txt"));
        // 下載文件到指定目錄
        //        emp.downLoad("bss\\example.txt", "E:\\example2.txt");

        // 刪除文件
        //        emp.delete("bss\\example.txt");

        // 關閉鏈接,防止文件服務器拋出 Connection reset by peer的錯誤
        emp.closeConnection();

    }
}

<!--ftp  -->
        <dependency>
            <groupId>commons-net</groupId>
            <artifactId>commons-net</artifactId>
            <version>3.3</version>
        </dependency>
apache

相關文章
相關標籤/搜索