天天看點

java通過FTPClient實作檔案在指定檔案夾的上傳下載下傳

文章轉載:

檔案上傳下載下傳:https://www.cnblogs.com/yingyujyf/p/6933823.html

建立目錄:https://blog.csdn.net/weixin_40582761/article/details/87185007

目錄絕對路徑相對路徑:https://blog.csdn.net/mqdxiaoxiao/article/details/107463378

通過FTPClient對象操作上傳下載下傳需要引入jar包commons-net-1.4.1.jar,maven依賴如下

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

ftpClient.retrieveFile方法用于下載下傳檔案

ftpClient.storeFile方法用于上傳檔案

ftpClient.makeDirectory建立目錄(隻能逐級建立,下面詳細說明)

ftpClient.changeWorkingDirectory("/"); // 切換到根目錄,絕對目錄

String dir = ftpClient.printWorkingDirectory(); // 擷取目前工作目錄

ftpClient.changeWorkingDirectory(dir); // 切換到目前目錄

是以,上傳下載下傳的方法需要将這兩個方法封裝進去

ftp工具類:

package ftp.ftp2;


import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import sun.net.TelnetOutputStream;
import sun.net.ftp.FtpProtocolException;

import java.io.*;
import java.net.SocketException;
import java.util.Properties;



public class FtpUtil {

    /**
     * 擷取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();
            } else {
                System.out.println("FTP連接配接成功。");
            }
        } catch (SocketException e) {
            e.printStackTrace();
            System.out.println("FTP的IP位址可能錯誤,請正确配置。");
        } catch (IOException e) {
            e.printStackTrace();
            System.out.println("FTP的端口錯誤,請正确配置。");
        }
        return ftpClient;
    }

    /*
     * 從FTP伺服器下載下傳檔案
     *
     * @param ftpHost FTP IP位址
     * @param ftpUserName FTP 使用者名
     * @param ftpPassword FTP使用者名密碼
     * @param ftpPort FTP端口
     * @param ftpPath FTP伺服器中檔案所在路徑 格式: ftptest/aa
     * @param localPath 下載下傳到本地的位置 格式:H:/download
     * @param fileName 檔案名稱
     */
    public static void 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);
            ftpClient.setControlEncoding("UTF-8"); // 中文支援
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);
            ftpClient.enterLocalPassiveMode();
            ftpClient.changeWorkingDirectory(ftpPath);

            File localFile = new File(localPath + File.separatorChar + fileName);
            OutputStream os = new FileOutputStream(localFile);
            ftpClient.retrieveFile(fileName, os);
            os.close();
            ftpClient.logout();

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

    }

    /**
     * Description: 向FTP伺服器上傳檔案
     * @param ftpHost FTP伺服器hostname
     * @param ftpUserName 賬号
     * @param ftpPassword 密碼
     * @param ftpPort 端口
     * @param ftpPath  FTP伺服器中檔案所在路徑 格式: ftptest/aa
     * @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);

            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;
    }

}
           

測試類:

package ftp.ftp2;

import java.io.*;

/**
 * Created by jyf on 2017/6/2.
 */
public class test {
    public static void main(String[] args) {
        String ftpHost = "172.16.114.10";
        String ftpUserName = "user";
        String ftpPassword = "a";
        int ftpPort = 21;
        String ftpPath = "test2/";
        String localPath = "F:\\11.txt";
        String fileName = "11.txt";

        //上傳一個檔案
        try{
            FileInputStream in=new FileInputStream(new File(localPath));
            boolean test = FtpUtil.uploadFile(ftpHost, ftpUserName, ftpPassword, ftpPort, ftpPath, fileName,in);
            System.out.println(test);
        } catch (FileNotFoundException e){
            e.printStackTrace();
            System.out.println(e);
        }

        //在FTP伺服器上生成一個檔案,并将一個字元串寫入到該檔案中
        try {
            InputStream input = new ByteArrayInputStream("test ftp jyf".getBytes("GBK"));
            boolean flag = FtpUtil.uploadFile(ftpHost, ftpUserName, ftpPassword, ftpPort, ftpPath, fileName,input);;
            System.out.println(flag);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }

        //下載下傳一個檔案
        FtpUtil.downloadFtpFile(ftpHost, ftpUserName, ftpPassword, ftpPort, ftpPath, localPath, fileName);
    }
}
           

實際項目中的上傳下載下傳可能需要對操作的檔案指定特定的目錄,比如上傳檔案到指定目錄,目錄不存在需要動态的建立目錄,對目錄的操作如下

Ftp建立目錄隻能逐級建立,你用建立目錄的方法不能直接/aaa/bbb/這麼建立要先建立aaa/,在/aaa/的目錄下再建立bbb/。

建立路徑示例

public static void main(String[] args) throws Exception {
    ConfigUtil instance = ConfigUtil.getInstance("/config.properties");
    FTPClient ftp = null;
    try {
      ftp = FtpUtil.getFTPClient(instance.getValue("ftp_ip"), instance.getValue("ftp_port"),
        instance.getValue("ftp_user"), instance.getValue("ftp_pwd"));
      ftp.setFileType(FTP.BINARY_FILE_TYPE);
      ftp.enterLocalPassiveMode();
      ftp.setDefaultTimeout(600000);
      ftp.setDataTimeout(600000);
      ftp.setSoTimeout(600000);
      ftp.setControlEncoding("GBK");
     
      String fileUrl = "/aaa/bbb/";
     
      if (!ftp.changeWorkingDirectory(fileUrl)) {
        System.err.println("不存在");
        boolean makeDirectory = ftp.makeDirectory(fileUrl);
        boolean changeWorkingDirectory = ftp.changeWorkingDirectory(fileUrl);
        System.err.println("建立:" + makeDirectory + ";切換:" + changeWorkingDirectory);
      } else {
        System.err.println("存在");
      }
     
    }catch (Exception e) {
      e.printStackTrace();
      throw e;
    }finally {
      if(ftp != null) {
        try {
          ftp.logout();
          ftp.disconnect();
        }
        catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
————————————————
版權聲明:本文為CSDN部落客「weixin_40582761」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_40582761/article/details/87185007
           

沒有/aaa/目錄會報錯,有會建立bbb/目錄

實際應用時可能沒有父目錄/aaa/,那麼就需要先建立父目錄/aaa/再建立bbb/子目錄,而這就是下面要示範的逐級建立

public static void main(String[] args) throws Exception {
    ConfigUtil instance = ConfigUtil.getInstance("/config.properties");
    FTPClient ftp = null;
    try {
      ftp = FtpUtil.getFTPClient(instance.getValue("ftp_ip"), instance.getValue("ftp_port"),
        instance.getValue("ftp_user"), instance.getValue("ftp_pwd"));
      ftp.setFileType(FTP.BINARY_FILE_TYPE);
      ftp.enterLocalPassiveMode();
      ftp.setDefaultTimeout(600000);
      ftp.setDataTimeout(600000);
      ftp.setSoTimeout(600000);
      ftp.setControlEncoding("GBK");
     
      String fileUrl = "/aaa/bbb/ccc";
     
      /*該部分為逐級建立*/
      String[] split = fileUrl.split("/");
     
      for (String str : split) {
        if(StringUtils.isBlank(str)) {
          continue;
        }
        if (!ftp.changeWorkingDirectory(str)) {
          System.err.println("不存在");
          boolean makeDirectory = ftp.makeDirectory(str);
          boolean changeWorkingDirectory = ftp.changeWorkingDirectory(str);
          System.err.println(str + "建立:" + makeDirectory + ";切換:" + changeWorkingDirectory);
        } else {
          System.err.println("存在");
        }
      }
     
    }catch (Exception e) {
      e.printStackTrace();
      throw e;
    }finally {
      if(ftp != null) {
        try {
          ftp.logout();
          ftp.disconnect();
        }
        catch (IOException e) {
          e.printStackTrace();
        }
      }
    }
  }
————————————————
版權聲明:本文為CSDN部落客「weixin_40582761」的原創文章,遵循CC 4.0 BY-SA版權協定,轉載請附上原文出處連結及本聲明。
原文連結:https://blog.csdn.net/weixin_40582761/article/details/87185007
           

操作目錄需要知道目錄的路徑,這時就有絕對路徑相對路徑一說了

這篇文章說的很好https://blog.csdn.net/mqdxiaoxiao/article/details/107463378

下面是直接轉載的上面連結的内容

根目錄

FTPClient的根目錄為"/"

切換到根目錄

ftpClient.changeWorkingDirectory("/"); // 切換到根目錄
String dir = ftpClient.printWorkingDirectory(); // 擷取目前工作目錄
System.out.println(dir); // 列印輸出目前工作目錄,輸出結果為"/"
           

絕對路徑

絕對路徑是以/開頭的,比如"/AA","/AA/BB","/AA/BB/CC/","/AA/BB/CC/test.txt"等

使用絕對路徑的話不受目前工作路徑的影響,

比如如下執行個體代碼使用changeWorkingDirectory("/A1/B1")方法切換目前工作路徑到/A1/B1檔案夾下

但是我們使用ftpClient.listNames("/A1/B2")絕對路徑擷取/A1/B2檔案夾下的檔案,并不受目前工作目錄的影響

記得絕對路徑一定是以/開頭的不要寫成"A1/B2",這樣的話就變成相對路徑了,就會受目前路徑的影響,相對路徑"A1/B2"轉化成絕對路徑其實就是目前工作目錄+相對路徑,也就是"/A1/B1/A1/B2"

對于相對路徑我們下面部分會再詳細說明

public static void main(String[] args) {
    try {
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(ftpIp, ftpPort);
        ftpClient.login(ftpName, ftpPws);
        ftpClient.enterLocalPassiveMode();
 
        ftpClient.changeWorkingDirectory("/A1/B1");
        System.out.println("目前工作目錄:" + ftpClient.printWorkingDirectory());
 
        String[] names = ftpClient.listNames("/A1/B2");
        System.out.println("/A1/B2目錄下的檔案:" + Arrays.toString(names));
    } catch (IOException e) {
        e.printStackTrace();
    }
}
           

輸出結果

目前工作目錄:/A1/B1

/A1/B2目錄下的檔案:[/A1/B2/b21.txt, /A1/B2/b22.txt]

相對路徑

相對路徑開頭沒有/

相對路徑的絕對路徑為目前路徑+相對路徑

如下執行個體先把目前工作目錄切換到A1,然後再通過changeWorkingDirectory("B1")切換到B1,由于是以傳入的是相對路徑,是以實際切換後的路徑是目前工作路徑+B1,也就是/A1/B1

最後再通過changeWorkingDirectory("/A1"),切換回A1目錄,注意這時候傳的是絕對路徑是以不受目前工作目錄影響,是以切換後的工作路徑是"/A1",而不是"/A1/B1/A1"

public static void main(String[] args) {
    try {
        FTPClient ftpClient = new FTPClient();
        ftpClient.connect(ftpIp, ftpPort);
        ftpClient.login(ftpName, ftpPws);
        ftpClient.enterLocalPassiveMode();
        
        ftpClient.changeWorkingDirectory("/A1");
        System.out.println("目前工作目錄:" + ftpClient.printWorkingDirectory());
 
        ftpClient.changeWorkingDirectory("B1");
        System.out.println("目前工作目錄:" + ftpClient.printWorkingDirectory());
 
        ftpClient.changeWorkingDirectory("/A1");
        System.out.println("目前工作目錄:" + ftpClient.printWorkingDirectory());
    } catch (IOException e) {
        e.printStackTrace();
    }
}
           

輸出結果為

目前工作目錄:/A1

目前工作目錄:/A1/B1

目前工作目錄:/A1

适用的方法

基本上FTPClient中所有關于檔案或檔案夾操作的方法都适用絕對路徑和相對路徑,有多個參數的方法還可以兩種方式同時使用,比如rename("B1/test.txt", "/A1/test.txt"),下面列出比較常見的方法

changeWorkingDirectory

listNames

retrieveFile

retrieveFileStream

storeFile

storeFileStream

makeDirectory

rename

總結

絕對路徑以"/"開頭

相對路徑不以"/"開頭

相對路徑轉成絕對路徑=目前工作目錄 + "/" + 絕對路徑

建議能使用絕對路徑就盡量不要使用相對路徑,因為相對路徑你能夠一目了然地知道你目前在操作的檔案路徑,而如果使用相對路徑的話很容易出現錯誤,因為FTP操作中經常會使用changeWorkingDirectory切換工作目錄,切來切去的話到最後你都不知道目前工作目錄是哪個

本篇文章其實是一個思考問題循序漸進的過程,你要上傳下載下傳檔案需要用ftpClient.retrieveFile方法用于下載下傳檔案,ftpClient.storeFile方法用于上傳檔案。上傳的話可能需要在遠端伺服器建立目錄将檔案上傳到此目錄下就要用到ftpClient.makeDirectory建立目錄(隻能逐級建立)。而建立目錄時需要将操作空間轉到目前目錄下才能操作

String dir = ftpClient.printWorkingDirectory(); // 擷取目前工作目錄

ftpClient.changeWorkingDirectory(dir); // 切換到目前目錄

是以順序是先将操作空間改變到指定目錄下,新增檔案夾,上傳檔案