使用Apache FTPClient 讀取文件信息


Maven依賴

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

使用案例

@Test
void testFtp() throws IOException {
    FTPClient ftpClient = new FTPClient();

    // 設置FTP服務器編碼,影響中文路徑讀取,常用windows:gbk,linux:utf-8
    ftpClient.setControlEncoding("GBK");

    ftpClient.connect("127.0.0.1", 21);
    ftpClient.login("usert", "1");

    // 設置傳輸文件類型,默認為 FTP.ASCII_FILE_TYPE,可能使換行符被替換導致文件被破壞
    ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

    try (InputStream in = ftpClient.retrieveFileStream("/test/中文.xlsx")) {
        // ...
    } finally {
        // 等待FTP Server返回226 Transfer complete
        ftpClient.completePendingCommand();
    }
}

解決讀取中文路徑亂碼

需要在連接之前設置FTP服務器的編碼

// 設置FTP服務器編碼,影響中文路徑讀取,常用windows:gbk,linux:utf-8
ftpClient.setControlEncoding("GBK");

ftpClient.connect("127.0.0.1", 21);

解決讀取excel(xlsx)時丟失字節

在linux下使用FTPClient下載部分xlsx文件時發生了文件損壞,對比發現文件丟失了部分字節。

解決這個問題需要在登錄之后、讀取文件之前修改文件傳輸類型

ftpClient.login("usert", "1");

// 設置傳輸文件類型,默認為 FTP.ASCII_FILE_TYPE,可能使換行符被替換導致文件被破壞
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

解決連續讀取文件流時,返回流為空

public InputStream retrieveFileStream(String remote) 
public OutputStream storeFileStream(String remote)

在使用上述方法讀取文件流后需要調用ftpClient.completePendingCommand(); 否則可能導致后續的部分其他操作失效。該方法會阻塞直到流的close()方法被調用。

當獲取的InputStream為空或者未獲取流而調用completePendingCommand()方法時,會導致程序卡住。

String dir = "/test";
FTPFile[] ftpFiles = ftpClient.listFiles(dir, FTPFile::isFile);
for (FTPFile ftpFile : ftpFiles) {
    String filePath = dir + "/" + ftpFile.getName();
    InputStream in = null;
    try {
        in = ftpClient.retrieveFileStream(filePath);

        System.out.println(in == null);
    } finally {
        if (in != null) {
            in.close();
            // 獲取文件流需要調用,此方法會阻塞直到流close()被調用
            ftpClient.completePendingCommand();
        }
    }
}

實測發現在流的close()方法前調用completePendingCommand()也可以正常工作

try (InputStream in = ftpClient.retrieveFileStream(filePath);){
    System.out.println(in == null);

    if (in != null) {
        // 獲取文件流需要調用,此方法會阻塞直到流被關閉
 	ftpClient.completePendingCommand();
    }
}

如果使用以下方法上傳、下載文件則不用也不該調用該方法

public boolean storeFile(String remote, InputStream local)
public boolean retrieveFile(String remote, OutputStream local)

獲取FTP上文件大小(字節)

使用FTPFile.getSize()

如果使用獲取InputStream + InputStream.available()方法,得到文件大小是可能存在誤差的,網絡傳輸存在誤差。

String dir = "/test";
FTPFile[] ftpFiles = ftpClient.listFiles(dir, FTPFile::isFile);
for (FTPFile ftpFile : ftpFiles) {
    System.out.println(ftpFile.getSize());
}

參考地址

FTPClient中使用completePendingCommand方法注意事項

FTPClient讀取文件流遇到的坑

使用Ftpclient從FTP上進行下載時文件少一個字節,打不開


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM