FTP的Java操作全面实战

3 篇文章 0 订阅

 FTP系列:
在Windows系统上搭建FTP服务器全面总结:https://blog.csdn.net/haoranhaoshi/article/details/86092630
FTP操作:https://blog.csdn.net/haoranhaoshi/article/details/86922363
FTP的Java操作全面实战:https://blog.csdn.net/haoranhaoshi/article/details/86922503

项目下载:https://download.csdn.net/download/haoranhaoshi/10952856

package ftptest;

public class FTPTest {
    public static void main(String[] args) {
        Ftp ftp = new Ftp();
        ftp.setIpAddr("192.168.1.10");
        ftp.setPort(21);
        ftp.setUserName("testUser");
        ftp.setPwd("Ty@123Ty");
        FtpUtil ftpUtil = new FtpUtil();
        try {
            // 连接FTP
            if (ftpUtil.connectFtp(ftp)) {
                System.out.println("FTP连接成功");
                System.out.println("----------------------------------------------");
                // 传入当前工作目录的子路径,改变服务端工作目录,根目录下有无/皆可,/ftpTest/ftpTest1等同于ftpTest/ftpTest1
                if (!ftpUtil.changeWorkingDirectory("/ftpTest/ftpTest1")) {
                    System.out.println("服务端路径错误");
                }

                // 得到当前服务端工作目录
                System.out.println("当前服务端工作目录" + ftpUtil.getWorkingDirectory());
                System.out.println("----------------------------------------------");

                // 得到当前工作目录下的所有文件夹和文件名
                System.out.println("-------当前工作目录下的所有文件夹和文件-------");
                for (String fileName : ftpUtil.getWorkingDirectoryFileNames()) {
                    System.out.println(fileName);
                }

                // 上传文件夹及其所有子文件夹或文件,合并相同目录,文件替换
                String uploadClientPath1 = "C:/Users/hao/Desktop/试试";
                String uploadServerPath1 = "/ftpTest";
                System.out.println("上传文件夹:" + uploadClientPath1 + ",到" + uploadServerPath1 + "," + (ftpUtil.upload(uploadServerPath1, uploadClientPath1, false, true) ? "成功" : "失败"));

                // 上传文件,已经存在会替换
                String uploadClientPath2 = "C:/Users/hao/Desktop/ftpTest1.txt";
                String uploadServerPath2 = "/";
                System.out.println("上传文件:" + uploadClientPath2 + ",到" + uploadServerPath2 + "," + (ftpUtil.upload(uploadServerPath2, uploadClientPath2, true, true) ? "成功" : "失败"));

                // 下载文件夹及其所有子文件和文件夹,已存在则删除重建
                String downloadServerPath1 = "/ftpTest";
                String downloadClientPath1 = "C:/Users/hao/Desktop";
                System.out.println("下载文件:" + downloadServerPath1 + ",到" + downloadClientPath1 + "," + (ftpUtil.downloadFile(downloadServerPath1, downloadClientPath1) ? "成功" : "失败"));

                // 下载文件,已存在则删除重建
                String downloadServerPath2 = "/ftpTest2.txt";
                String downloadClientPath2 = "C:/Users/hao/Desktop";
                System.out.println("下载文件:" + downloadServerPath2 + ",到" + downloadClientPath2 + "," + (ftpUtil.downloadFile(downloadServerPath2, downloadClientPath2) ? "成功" : "失败"));
            } else {
                System.out.println("FTP连接失败");
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        ftpUtil.closeFtp();
    }
}
package ftptest;

import java.io.*;

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

/**
 * Ftp工具类 需要导入commons-net-3.6.jar这个包
 */
public class FtpUtil {

    private FTPClient ftpClient;

    /**
     * 本地字符编码
     */
    private static String CLIENT_CHARSET = "GBK";

    /**
     * FTP协议里面,规定文件名编码为ISO-8859-1
     */
    private static String SERVER_CHARSET = "ISO-8859-1";

    /**
     * 获取ftp连接
     *
     * @param ftp
     * @return
     * @throws Exception
     */
    public boolean connectFtp(Ftp ftp) throws Exception {
        ftpClient = new FTPClient();
        boolean flag = true;
        int reply;
        try {
            ftpClient.connect(ftp.getIpAddr(), ftp.getPort());
            // ftp登陆
            if (ftpClient.login(ftp.getUserName(), ftp.getPwd())) {
                return false;
            }
            // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK)
            if (FTPReply.isPositiveCompletion(ftpClient.sendCommand("OPTS UTF8", "ON"))) {
                CLIENT_CHARSET = "UTF-8";
            }

            ftpClient.setControlEncoding(CLIENT_CHARSET);
            // 设置被动模式
            ftpClient.enterLocalPassiveMode();
            // 设置文件传输类型
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

            // 检查延时
            reply = ftpClient.getReplyCode();
            // 如果延时不在200到300之间,就关闭连接
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                flag = false;
            }
        } catch (Exception e) {
            flag = false;
            throw new Exception(e.getMessage());
        } finally {
            return flag;
        }
    }

    /**
     * 关闭ftp连接
     */
    public void closeFtp() {
        if (ftpClient != null && ftpClient.isConnected()) {
            try {
                ftpClient.logout();
                ftpClient.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 传入服务端从根目录开始的完整文件路径,改变当前服务端工作目录
     */
    public boolean changeWorkingDirectory(String serverPath) {
        try {
            while (!this.getWorkingDirectory().equals("/")) {
                ftpClient.changeToParentDirectory();
            }

            return ftpClient.changeWorkingDirectory(clientCharsetToServer(serverPath));
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 客户端编码转成FTP协议编码,防止中文路径在服务端无法识别
     *
     * @param dirName 客户端GBK或者UTF-8编码
     */
    private String clientCharsetToServer(String dirName) {
        try {
            return new String(dirName.getBytes(CLIENT_CHARSET), SERVER_CHARSET);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return dirName;
        }
    }

    /**
     * FTP协议编码转成客户端编码,防止服务端中文路径乱码
     *
     * @param dirName 服务端FTP协议ISO-8859-1编码
     */
    private String serverCharsetToClient(String dirName) {
        try {
            return new String(dirName.getBytes(SERVER_CHARSET), CLIENT_CHARSET);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
            return dirName;
        }
    }

    /**
     * 得到当前服务端工作目录
     */
    public String getWorkingDirectory() {
        try {
            return serverCharsetToClient(ftpClient.printWorkingDirectory());
        } catch (IOException e) {
            e.printStackTrace();
            return "";
        }
    }

    /**
     * 上传文件或文件夹
     *
     * @param serverDirPath    服务端路径
     * @param clientFilePath   客户端文件路径
     * @param isCoverDirectory 文件夹已存在是否覆盖,是则删除重建,否则不删
     * @param isCoverFile      文件已存在是否覆盖,是则删除重建,否则不删
     * @throws Exception
     */
    public boolean upload(String serverDirPath, String clientFilePath, boolean isCoverDirectory, boolean isCoverFile) throws Exception {
        System.out.println("------------------上传文件--------------------");
        if (serverDirPath != null) {
            if (!this.changeWorkingDirectory(serverDirPath)) {
                System.out.println("服务端路径错误");
                return false;
            }
        }

        System.out.println("当前服务端工作目录:" + getWorkingDirectory());
        File file = new File(clientFilePath);
        // 防止中文目录创建失败或者中文名的文件上传失败
        String currentFileName = clientCharsetToServer(file.getName());
        if (file.isDirectory()) {
            if (isWorkingDirectoryHasFile(currentFileName)) {
                System.out.print("服务端工作目录" + file.getName() + "已存在" + ",");
                if (isCoverDirectory) {
                    if (ftpClient.deleteFile(currentFileName)) {
                        System.out.print("已删除");
                        // 在服务端当前目录创建名称为currentFileName的文件夹
                        if (ftpClient.makeDirectory(currentFileName)) {
                            System.out.print("已重建");
                        } else {
                            System.out.print("重建失败");
                        }
                    } else {
                        System.out.print("删除失败\n");
                        return false;
                    }
                } else {
                    System.out.print("保持不变");
                }

                System.out.print("\n");
            } else {
                System.out.print("服务端工作目录" + file.getName() + "不存在,");
                // 在服务端当前目录创建名称为currentFileName的文件夹
                if (ftpClient.makeDirectory(currentFileName)) {
                    System.out.print("已创建");
                } else {
                    System.out.print("创建失败");
                }

                System.out.print("\n");
            }

            String[] fileNames = file.list();
            if (fileNames == null || fileNames.length == 0) {
                return true;
            }

            if (ftpClient.changeWorkingDirectory(currentFileName)) {
                System.out.println("进入服务端工作目录" + file.getName());
            }

            for (String fileName : fileNames) {
                upload(null, file.getPath() + "/" + fileName, isCoverDirectory, isCoverFile);
            }

            if (!ftpClient.changeToParentDirectory()) {
                System.out.println("返回上一级目录失败");
            }
        } else {
            if (isWorkingDirectoryHasFile(currentFileName)) {
                System.out.print("当前服务端工作目录下存在文件:" + file.getName() + ",");
                if (isCoverFile) {
                    FileInputStream fileInputStream = new FileInputStream(file);
                    // 在服务端当前目录创建名称为currentFileName,文件流为fileInputStream,对应路径filePath的文件
                    if (ftpClient.storeFile(currentFileName, fileInputStream)) {
                        System.out.print("已覆盖");
                    } else {
                        System.out.print("覆盖失败");
                    }

                    fileInputStream.close();
                } else {
                    System.out.print("不覆盖");
                }
            } else {
                System.out.print("当前服务端工作目录下不存在文件:" + file.getName() + ",");
                FileInputStream fileInputStream = new FileInputStream(file);
                // 在服务端当前目录创建名称为currentFileName,文件流为fileInputStream,对应路径filePath的文件
                if (ftpClient.storeFile(currentFileName, fileInputStream)) {
                    System.out.print("已存储");
                } else {
                    System.out.print("存储失败");
                }

                fileInputStream.close();
            }

            System.out.print("\n");
        }

        return true;
    }

    /**
     * 当前工作目录下是否有查询的文件
     *
     * @param fileName
     * @return
     */
    public boolean isWorkingDirectoryHasFile(String fileName) {
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles();
            for (FTPFile ftpFile : ftpFiles) {
                if (ftpFile.getName().equals(fileName)) {
                    return true;
                }
            }

            return false;
        } catch (IOException e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 得到当前工作目录下的所有文件夹和文件名
     */
    public String[] getWorkingDirectoryFileNames() {
        try {
            FTPFile[] ftpFiles = ftpClient.listFiles();
            String[] fileNames = new String[ftpFiles.length];
            int i = 0;
            for (FTPFile ftpFile : ftpFiles) {
                fileNames[i++] = serverCharsetToClient(ftpFile.getName());
            }

            return fileNames;
        } catch (IOException e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 获得对应服务器路径下的文件,默认使当前服务端目录转移至此文件目录
     *
     * @param serverPath 服务器路径
     */
    public FTPFile getFTPFile(String serverPath) {
        String serverFileName = serverPath;
        if (serverFileName.indexOf("/") != -1) {
            String[] pathItem = serverFileName.split("/");
            serverFileName = pathItem[pathItem.length - 1];
        }

        String serverDirectory = serverCharsetToClient(serverPath.substring(0, serverPath.length() - ("/" + serverFileName).length()));

        if (changeWorkingDirectory(serverDirectory)) {
            try {
                for (FTPFile ftpFile : ftpClient.listFiles()) {
                    if (ftpFile.getName().equals(serverFileName)) {
                        return ftpFile;
                    }
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        } else {
            System.out.println("服务端工作目录:" + serverDirectory + "不存在");
        }

        return null;
    }

    /**
     * 下载FTP文件,本地文件已存在则覆盖
     *
     * @param serverPath 服务器路径
     * @param clientPath 本地路径
     */
    public boolean downloadFile(String serverPath, String clientPath) {
        serverPath = clientCharsetToServer(serverPath);
        System.out.println("------------------下载文件--------------------");
        File clientDirectory = new File(clientPath);
        // 如果文件夹路径不存在,则创建文件夹
        if (!clientDirectory.exists()) {
            System.out.print("客户端目录:" + clientPath + "不存在,");
            if (clientDirectory.mkdirs()) {
                System.out.print("已创建");
            } else {
                System.out.print("创建失败\n");
                return false;
            }

            System.out.print("\n");
        }

        FTPFile ftpFile = getFTPFile(serverPath);
        System.out.println("当前服务端工作目录:" + this.getWorkingDirectory());
        if (ftpFile == null) {
            System.out.println("服务端工作目录:" + serverCharsetToClient(serverPath) + "不存在");
            return false;
        }

        String clientFilePath = clientPath + "/" + serverCharsetToClient(ftpFile.getName());
        File clientFile = new File(clientFilePath);

        if (ftpFile.isFile()) {
            // 判断文件是否存在,存在则删除重新下载
            if (clientFile.exists()) {
                System.out.print("文件" + clientFilePath + "已存在,");
                if (clientFile.delete()) {
                    System.out.print("已删除");
                } else {
                    System.out.print("删除失败\n");
                    return false;
                }

                System.out.print("\n");
            }

            try {
                OutputStream outputStream = new FileOutputStream(clientFilePath);
                // 将服务端当前目录下ftpFile.getName()名称的文件输出到本地路径clientFilePath下
                boolean isSuccess = ftpClient.retrieveFile(ftpFile.getName(), outputStream);
                outputStream.flush();
                outputStream.close();
                System.out.println("下载文件:" + clientFilePath + "," + (isSuccess ? "成功" : "失败"));
                return isSuccess;
            } catch (Exception e) {
                e.printStackTrace();
                return false;
            }
        } else {
            if (clientFile.exists()) {
                System.out.println("文件夹" + clientFilePath + "已存在,");
            }else{
                if (clientFile.mkdirs()) {
                    System.out.println("客户端目录:" + clientFilePath + "已建立");
                } else {
                    System.out.println("客户端目录:" + clientFilePath + "建立失败");
                    return false;
                }
            }

            try {
                System.out.println("进入服务端工作目录:" + serverCharsetToClient(ftpFile.getName()));
                if (!ftpClient.changeWorkingDirectory(ftpFile.getName())) {
                    System.out.println(",失败");
                    return false;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            try {
                for (FTPFile ftpFile1 : ftpClient.listFiles()) {
                    downloadFile(serverCharsetToClient(serverPath + "/" + ftpFile1.getName()), clientFilePath);
                }
            } catch (IOException e) {
                e.printStackTrace();
            }

            return true;
        }
    }
}

package ftptest;

/**
 * ftp链接常量
 */
public class Ftp {
    /**
     * ip地址
     */
    private String ipAddr;

    /**
     * 端口号
     */
    private Integer port;

    /**
     * 用户名
     */
    private String userName;

    /**
     * 密码
     */
    private String pwd;

    public String getIpAddr() {
        return ipAddr;
    }

    public void setIpAddr(String ipAddr) {
        this.ipAddr = ipAddr;
    }

    public Integer getPort() {
        return port;
    }

    public void setPort(Integer port) {
        this.port = port;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public String getPwd() {
        return pwd;
    }

    public void setPwd(String pwd) {
        this.pwd = pwd;
    }
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风铃峰顶

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值