FTP服務簡介與java實現ftp上傳下載

FTP簡介

FTP(File Transfer Protocol)是因特網中使用最廣泛的文件傳輸協議。FTP協議是應用層協議,它是基於TCP協議的。FTP是一個客戶/服務器系統。

FTP的兩種傳輸模式(主動模式和被動模式)

關於主動還是被動都是針對於FTP服務器來說的,是選擇主動模式還是被動模式是由客戶端決定的。

主動模式


ftp主動模式過程大致如下:

1、客戶端隨機選取一個大於1024的非特權端口與FTP服務器的21號端口進行控制連接,由於FTP是基於TCP的,這個過程要經歷三次握手。連接成功後,以後客戶端與服務器之間的控制命令如上傳、下載、切換路徑等命令都是通過控制連接來傳輸的。

2、當需要進行數據連接且客戶端選擇發起的是主動模式的連接時,客戶端會隨機選擇一個端口portB,通過命令通道發送到FTP服務器,並等待FTP服務器主動發起FTP數據連接。

3、FTP服務器收到了客戶端的請求,並主動通過20號端口向客戶端的portB發起數據連接,這個過程也是有三次握手的。

這樣在客戶機與FTP服務器就建立了兩個連接,一個控制連接用於傳輸命令,一個數據連接用於傳輸數據。

ftp連接在客戶端沒有發起數據請求時是不會馬上建立數據連接的。FTP上控制連接端口號是21,數據連接端口號是20

被動模式

被動模式解析:

1、建立控制連接、同主動模式。

2、當需要數據連接時,客戶端向ftp服務器發起被動模式請求,等待服務器的迴應。

3、服務器接收到請求並開啓一個監聽的端口號pasvPortftp服務器通過命令通過告知客戶機自己的被動連接端口pasvPort,等待客戶端發起連接。

4、客戶機向隨機選取一個portBftp服務器的pasvPort端口發起數據連接

可以看到被動模式的FTP數據連接是由客戶機主動發起的。

在Java項目中如何使用FTP服務

1、使用的是FTPClient,需要在maven中添加依賴:

<dependency>
	<groupId>commons-net</groupId>
<artifactId>commons-net</artifactId>
    <version>1.4.1</version>
</dependency>

2、新建了一個FTPUtil工具類,用來管理FTP的連接、上傳和下載。

public class FtpUtil {
	public static final String ftpHost = "111.231.250.43";
	public static final String ftpUserName = "lcl";
	public static final String ftpPassword = "123";
	public static final int ftpPort = 21;
	public static final String ftpPath = "appdata/service/";
	public static final String ftpPathClient = "appdata/client/";
	public static final String uploadPath = System.getProperty("user.dir");
	/**
     * 獲取FTPClient對象
     *
     * @param ftpHost     FTP主機服務器
     * @param ftpPassword FTP 登錄密碼
     * @param ftpUserName FTP登錄用戶名
     * @param ftpPort     FTP端口 默認爲21
     * @return
     */
    public static FTPClient getFTPClient(String ftpHost, String ftpUserName,
                                         String ftpPassword, int ftpPort) {
        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient = new FTPClient();
            ftpClient.connect(ftpHost, ftpPort);// 連接FTP服務器
            ftpClient.login(ftpUserName, ftpPassword);// 登陸FTP服務器
            if (!FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
                System.out.println("未連接到FTP,用戶名或密碼錯誤。");
                ftpClient.disconnect();
                return null;
            } else {
                System.out.println("FTP連接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            System.out.println("FTP的IP地址可能錯誤,請正確配置。");
            return null;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("FTP的端口錯誤,請正確配置。");
            return null;
        }
        return ftpClient;
    }

    /*
     * 從FTP服務器下載文件
     *
     * @param ftpHost FTP IP地址
     * @param ftpUserName FTP 用戶名
     * @param ftpPassword FTP用戶名密碼
     * @param ftpPort FTP端口
     * @param ftpPath FTP服務器中文件所在路徑 格式: appdata/service/年月/
     * @param localPath 下載到本地的位置 格式:xx/upload/
     * @param fileName 文件名稱  如 app_20180803.zip
     */
    public static boolean downloadFtpFile(String ftpHost, String ftpUserName,
    		String ftpPassword, int ftpPort, String ftpPath, String localPath,String fileName) {
        FTPClient ftpClient = null;
        try {
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            if(ftpClient == null){
            	//ftp連接不上返回false
            	return false;
            }
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            //客戶機進入ftp的被動模式,主動向FTP服務器發起數據連接
            ftpClient.enterLocalPassiveMode();
            //切換到服務器的指定路徑下
            ftpClient.changeWorkingDirectory(ftpPath);
            //創建要下載的文件
            File localFile = new File(localPath+fileName);
            if(!localFile.exists()){
            	localFile.createNewFile();
            }
            OutputStream os = new FileOutputStream(localFile);
            //retrieveFile方法將當前路徑下名爲fileName的文件放到os輸出流中,即進行文件下載
            boolean flag = ftpClient.retrieveFile(fileName, os);
            os.flush();
            os.close();
            ftpClient.logout();
            if(!flag){
            	return false;
            }
            return true;

        } catch (FileNotFoundException e) {
            System.out.println("沒有找到" + ftpPath + "文件");
            e.printStackTrace();
            return false;
        } catch (SocketException e) {
            System.out.println("連接FTP失敗.");
            e.printStackTrace();
            return false;
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("文件讀取錯誤。");
            e.printStackTrace();
            return false;
        }
    }

    /**
     * Description: 向FTP服務器上傳文件
     * @param ftpHost FTP服務器hostname
     * @param ftpUserName 賬號
     * @param ftpPassword 密碼
     * @param ftpPort 端口
     * @param ftpPath  FTP服務器中文件所在路徑 格式: appdata/client/
     * @param fileName ftp文件名稱
     * @param input 文件流
     * @return 成功返回true,否則返回false
     */
    public static boolean uploadFile(String ftpHost, String ftpUserName,
                                     String ftpPassword, int ftpPort, String ftpPath,
                                     String fileName,InputStream input) {
        boolean success = false;
        FTPClient ftpClient = null;
        try {
            int reply;
            ftpClient = getFTPClient(ftpHost, ftpUserName, ftpPassword, ftpPort);
            reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                return success;
            }
            ftpClient.setControlEncoding("UTF-8"); // 中文支持
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);
            String dirName = DateHelper.getYearAndMonth();
            //向服務器上查詢文件是否存在,若不存在則創建文件
            ftpClient.makeDirectory(dirName);
            //切換到創建的文件夾下
            ftpClient.changeWorkingDirectory(dirName);
            //在ftp服務器上新建一個叫fileName發文件,並將input輸入流中的內容寫入fileName
            ftpClient.storeFile(fileName, input);
            input.close();
            ftpClient.logout();
            success = true;
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.disconnect();
                } catch (IOException ioe) {
                }
            }
        }
        return success;
    }
}



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章