今天被ftp上中文名修改坑了好久

项目用的是 apache commons 里的 FtpClient 实现的对ftp文件的上传下载操作,今天增加了业务要修改ftp上的文件名,然后就一直的报错,问题是它修改名字的方法只返回一个boolean,没有异常,这就很蛋疼了,找了好久才发现是中文的名字的原因

改名

直接上代码

package net.codejava.ftp;

import java.io.IOException;

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

public class FTPRenamer {

    public static void main(String[] args) {
        String server = "www.ftpserver.com";
        int port = 21;
        String user = "username";
        String pass = "password";

        FTPClient ftpClient = new FTPClient();
        try {
            ftpClient.connect(server, port);
            ftpClient.login(user, pass);

            // renaming directory
            String oldDir = "/photo";
            String newDir = "/photo_2012";

            boolean success = ftpClient.rename(oldDir, newDir);
            if (success) {
                System.out.println(oldDir + " was successfully renamed to: "
                        + newDir);
            } else {
                System.out.println("Failed to rename: " + oldDir);
            }

            // renaming file
            String oldFile = "/work/error.png";
            String newFile = "/work/screenshot.png";

            success = ftpClient.rename(oldFile, newFile);
            if (success) {
                System.out.println(oldFile + " was successfully renamed to: "
                        + newFile);
            } else {
                System.out.println("Failed to rename: " + oldFile);
            }

            ftpClient.logout();
            ftpClient.disconnect();
        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            if (ftpClient.isConnected()) {
                try {
                    ftpClient.logout();
                    ftpClient.disconnect();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

如果修改的名字里没有中文,用上面的代码就够了,但如果有中文就要对文件名进行转码了,转码代码如下

// renaming file
String oldFile = "/work/你好.png";
String newFile = "/work/世界.png";

success = ftpClient.rename(
    new String(oldFile.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1),
    new String(newFile.getBytes(StandardCharsets.UTF_8), StandardCharsets.ISO_8859_1)
);

这样再修改名字就没有问题了

顺便记录一下上传、下载、删除、检查文件是否存在,同样的,如果有中文名,最好先转一下码再进行操作

上传

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

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

/**
 * A program that demonstrates how to upload files from local computer
 * to a remote FTP server using Apache Commons Net API.
 * @author www.codejava.net
 */
public class FTPUploadFileDemo {

    public static void main(String[] args) {
        String server = "www.myserver.com";
        int port = 21;
        String user = "user";
        String pass = "pass";

        FTPClient ftpClient = new FTPClient();
        try {

            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            ftpClient.enterLocalPassiveMode();

            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // APPROACH #1: uploads first file using an InputStream
            File firstLocalFile = new File("D:/Test/Projects.zip");

            String firstRemoteFile = "Projects.zip";
            InputStream inputStream = new FileInputStream(firstLocalFile);

            System.out.println("Start uploading first file");
            boolean done = ftpClient.storeFile(firstRemoteFile, inputStream);
            inputStream.close();
            if (done) {
                System.out.println("The first file is uploaded successfully.");
            }

            // APPROACH #2: uploads second file using an OutputStream
            File secondLocalFile = new File("E:/Test/Report.doc");
            String secondRemoteFile = "test/Report.doc";
            inputStream = new FileInputStream(secondLocalFile);

            System.out.println("Start uploading second file");
            OutputStream outputStream = ftpClient.storeFileStream(secondRemoteFile);
            byte[] bytesIn = new byte[4096];
            int read = 0;

            while ((read = inputStream.read(bytesIn)) != -1) {
                outputStream.write(bytesIn, 0, read);
            }
            inputStream.close();
            outputStream.close();

            boolean completed = ftpClient.completePendingCommand();
            if (completed) {
                System.out.println("The second file is uploaded successfully.");
            }

        } catch (IOException ex) {
            System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

}

下载

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

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

/**
 * A program demonstrates how to upload files from local computer to a remote
 * FTP server using Apache Commons Net API.
 * @author www.codejava.net
 */
public class FTPDownloadFileDemo {

    public static void main(String[] args) {
        String server = "www.myserver.com";
        int port = 21;
        String user = "user";
        String pass = "pass";

        FTPClient ftpClient = new FTPClient();
        try {

            ftpClient.connect(server, port);
            ftpClient.login(user, pass);
            ftpClient.enterLocalPassiveMode();
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);

            // APPROACH #1: using retrieveFile(String, OutputStream)
            String remoteFile1 = "/test/video.mp4";
            File downloadFile1 = new File("D:/Downloads/video.mp4");
            OutputStream outputStream1 = new BufferedOutputStream(new FileOutputStream(downloadFile1));
            boolean success = ftpClient.retrieveFile(remoteFile1, outputStream1);
            outputStream1.close();

            if (success) {
                System.out.println("File #1 has been downloaded successfully.");
            }

            // APPROACH #2: using InputStream retrieveFileStream(String)
            String remoteFile2 = "/test/song.mp3";
            File downloadFile2 = new File("D:/Downloads/song.mp3");
            OutputStream outputStream2 = new BufferedOutputStream(new FileOutputStream(downloadFile2));
            InputStream inputStream = ftpClient.retrieveFileStream(remoteFile2);
            byte[] bytesArray = new byte[4096];
            int bytesRead = -1;
            while ((bytesRead = inputStream.read(bytesArray)) != -1) {
                outputStream2.write(bytesArray, 0, bytesRead);
            }

            success = ftpClient.completePendingCommand();
            if (success) {
                System.out.println("File #2 has been downloaded successfully.");
            }
            outputStream2.close();
            inputStream.close();

        } catch (IOException ex) {
            System.out.println("Error: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

删除

import java.io.IOException;

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

public class FTPDeleteFileDemo {

    public static void main(String[] args) {
        String server = "www.myserver.com";
        int port = 21;
        String user = "user";
        String pass = "pass";

        FTPClient ftpClient = new FTPClient();
        try {

            ftpClient.connect(server, port);

            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                System.out.println("Connect failed");
                return;
            }

            boolean success = ftpClient.login(user, pass);

            if (!success) {
                System.out.println("Could not login to the server");
                return;
            }
            String fileToDelete = "/repository/video/cool.mp4";

            boolean deleted = ftpClient.deleteFile(fileToDelete);
            if (deleted) {
                System.out.println("The file was deleted successfully.");
            } else {
                System.out.println("Could not delete the  file, it may not exist.");
            }

        } catch (IOException ex) {
            System.out.println("Oh no, there was an error: " + ex.getMessage());
            ex.printStackTrace();
        } finally {
            // logs out and disconnects from server
            try {
                if (ftpClient.isConnected()) {
                    ftpClient.logout();
                    ftpClient.disconnect();
                }
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }

}

检查文件/文件夹是否存在

package net.codejava.ftp;

import java.io.IOException;
import java.io.InputStream;
import java.net.SocketException;

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

/**
 * This program demonstrates how to determine existence of a specific
 * file/directory on a remote FTP server.
 * @author www.codejava.net
 *
 */
public class FTPCheckFileExists {
    private FTPClient ftpClient;
    private int returnCode;

    /**
     * Determines whether a directory exists or not
     * @param dirPath
     * @return true if exists, false otherwise
     * @throws IOException thrown if any I/O error occurred.
     */
    boolean checkDirectoryExists(String dirPath) throws IOException {
        ftpClient.changeWorkingDirectory(dirPath);
        returnCode = ftpClient.getReplyCode();
        if (returnCode == 550) {
            return false;
        }
        return true;
    }

    /**
     * Determines whether a file exists or not
     * @param filePath
     * @return true if exists, false otherwise
     * @throws IOException thrown if any I/O error occurred.
     */
    boolean checkFileExists(String filePath) throws IOException {
        InputStream inputStream = ftpClient.retrieveFileStream(filePath);
        returnCode = ftpClient.getReplyCode();
        if (inputStream == null || returnCode == 550) {
            return false;
        }
        return true;
    }

    /**
     * Connects to a remote FTP server
     */
    void connect(String hostname, int port, String username, String password)
            throws SocketException, IOException {
        ftpClient = new FTPClient();
        ftpClient.connect(hostname, port);
        returnCode = ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(returnCode)) {
            throw new IOException("Could not connect");
        }
        boolean loggedIn = ftpClient.login(username, password);
        if (!loggedIn) {
            throw new IOException("Could not login");
        }
        System.out.println("Connected and logged in.");
    }

    /**
     * Logs out and disconnects from the server
     */
    void logout() throws IOException {
        if (ftpClient != null && ftpClient.isConnected()) {
            ftpClient.logout();
            ftpClient.disconnect();
            System.out.println("Logged out");
        }
    }

    /**
     * Runs this program
     */
    public static void main(String[] args) {
        String hostname = "www.yourserver.com";
        int port = 21;
        String username = "your_user";
        String password = "your_password";
        String dirPath = "Photo";
        String filePath = "Music.mp4";

        FTPCheckFileExists ftpApp = new FTPCheckFileExists();

        try {
            ftpApp.connect(hostname, port, username, password);

            boolean exist = ftpApp.checkDirectoryExists(dirPath);
            System.out.println("Is directory " + dirPath + " exists? " + exist);

            exist = ftpApp.checkFileExists(filePath);
            System.out.println("Is file " + filePath + " exists? " + exist);

        } catch (IOException ex) {
            ex.printStackTrace();
        } finally {
            try {
                ftpApp.logout();
            } catch (IOException ex) {
                ex.printStackTrace();
            }
        }
    }
}

参考

原文链接: https://tomoya92.github.io/2019/08/15/java-ftp/