FTP--03--FtpUtil

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


FtpUtil


import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPFile;
import org.apache.commons.net.ftp.FTPFileFilter;
import org.apache.commons.net.ftp.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.SocketException;
import java.nio.charset.StandardCharsets;


public class FtpUtil {
    private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);
    private static final String SERVER_CHARSET = "ISO-8859-1";

    //ftp对象
    private FTPClient ftp;
    private final String ip;
    private final int port;
    private final String name;
    private final String pwd;
    private String localCharset = "GBK";

    public FtpUtil(String ip, int port, String name, String pwd) {
        this.ip = ip;
        this.port = port;
        this.name = name;
        this.pwd = pwd;
    }

    public void testConnect() {
        getFtpClient();
    }

    /**
     * 获取ftpclient初始方法
     */
    private boolean getFtpClient() {
        // 双重检索机制
        if (ftp == null) {
            synchronized (this) {
                if (ftp == null) {
                    ftp = new FTPClient();
                    //验证登录
                    return connect();
                }
            }
        } else if (!ftp.isConnected()) {
            connect();
        }
        return ftp.isConnected();
    }

    private boolean connect() {
        try {
            ftp.connect(this.ip, this.port);
            ftp.login(this.name, this.pwd);
            if (!FTPReply.isPositiveCompletion(ftp.getReplyCode())) {
                logger.info("【ftp用户名或密码错误】-连接失败!");
                ftp.disconnect();
            } else {
                int reply;
                reply = ftp.getReplyCode();
                if (!FTPReply.isPositiveCompletion(reply)) {
                    ftp.disconnect();
                    logger.info("【ftp连接失败】");
                    return false;
                }
                if (FTPReply.isPositiveCompletion(ftp.sendCommand("OPTS UTF8", "ON"))) {
                    // 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
                    localCharset = "UTF-8";
                }
                ftp.setControlEncoding(localCharset);
                ftp.setCharset(StandardCharsets.UTF_8);
                ftp.setFileType(FTP.BINARY_FILE_TYPE);
                ftp.enterLocalPassiveMode();
                logger.info("【ftp连接成功】-文件编码采用:{}", localCharset);
                return true;
            }
        } catch (IOException e) {
            logger.warn("【获取ftp客户端连接异常】,异常堆栈:", e);
        }
        return false;
    }

    /**
     * 从FTP服务器下载文件
     *
     * @param ftpPath     FTP服务器中文件所在路径
     * @param ftpFileName FTP服务器中文件名
     * @param localPath   下载到本地的位置
     * @param fileName    文件名称
     */
    public boolean downloadFtpFile(String ftpPath, String ftpFileName, String localPath, String fileName) {
        boolean isAppend = false;
        OutputStream os = null;
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);
            ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
            ftp.changeWorkingDirectory(ftpPath);
            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            File localFile = new File(localPath + File.separatorChar + fileName);
            if(!localFile.exists()){
                localFile.getParentFile().mkdirs();
            }
            os = new FileOutputStream(localFile);
            isAppend = ftp.retrieveFile(new String(ftpFileName.getBytes(localCharset), SERVER_CHARSET), os);
            logger.info("【下载ftp文件返回状态码】: {}", ftp.getReplyCode());
            os.close();
            ftp.logout();
            if (isAppend) {
                logger.info("【下载ftp文件成功】 文件名: {}", ftpFileName);
            }else{
                //文件不存在,删除本地文件
                localFile.delete();
            }
            return isAppend;
        } catch (FileNotFoundException e) {
            logger.warn("【ftp文件不存在】,文件名称:{},文件路径:{},异常堆栈:", fileName, ftpPath, e);
        } catch (SocketException e) {
            logger.warn("【ftp连接失败】,异常堆栈:", e);
        } catch (IOException e) {
            logger.info("【下载ftp文件异常】,异常堆栈:", e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.info(ioe.getMessage(), ioe);
                }
            }
            if (os != null) {
                try {
                    os.close();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
        return isAppend;
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param ftpPath  FTP服务器中文件所在路径 格式: ftptest/aa
     * @param tempName 上传过程中的文件名,有.now后缀
     * @param fileName 上传完成的文件名
     * @param input    文件流
     * @return 成功返回true,否则返回false
     */
    public boolean uploadFile(String ftpPath, String tempName, String fileName, InputStream input) {
        boolean success = false;
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
            ftp.makeDirectory(ftpPath);
            ftp.changeWorkingDirectory(ftpPath);
            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            tempName = new String(tempName.getBytes(localCharset), SERVER_CHARSET);
            fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
            success = ftp.storeFile(tempName, input);
            logger.info("【上传ftp文件返回状态码】: {}", ftp.getReplyCode());
            ftp.rename(tempName, fileName);
            logger.info("【修改ftp文件名返回状态码】: {}", ftp.getReplyCode());
            if (success) {
                logger.info("【上传ftp文件成功】,文件名: {}", fileName);
            }
            ftp.logout();
        } catch (IOException e) {
            logger.warn("【上传文件至ftp异常】,文件名: {},异常堆栈:", fileName, e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.info(ioe.getMessage(), ioe);
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
        return success;
    }

    /**
     * Description: 向FTP服务器上传文件
     *
     * @param ftpPath  FTP服务器中文件所在路径 格式: ftptest/aa
     * @param fileName 上传完成的文件名
     * @param input    文件流
     * @return 成功返回true,否则返回false
     */
    public boolean uploadFile(String ftpPath, String fileName, InputStream input) {
        boolean success = false;
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
            ftp.makeDirectory(ftpPath);
            ftp.changeWorkingDirectory(ftpPath);
            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
            success = ftp.storeFile(fileName, input);
            logger.info("【上传ftp文件返回状态码】: {}", ftp.getReplyCode());
            if (success) {
                logger.info("【上传ftp文件成功】,文件名: {}", fileName);
            }
            ftp.logout();
        } catch (IOException e) {
            logger.warn("【上传文件至ftp异常】,文件名: {},异常堆栈:", fileName, e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.info(ioe.getMessage(), ioe);
                }
            }
            if (input != null) {
                try {
                    input.close();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
        return success;
    }

    /**
     * 修改文件路径
     *
     * @param oldPath  原文件夹
     * @param newPath  新的文件夹
     * @param fileName 要移动的文件名称
     * @return
     */
    public boolean rename(String oldPath, String newPath, String fileName) {
        boolean isAppend = false;
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            oldPath = new String(oldPath.getBytes(localCharset), SERVER_CHARSET);
            newPath = new String(newPath.getBytes(localCharset), SERVER_CHARSET);
            ftp.changeWorkingDirectory(oldPath);
            ftp.makeDirectory(newPath);
            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);
            isAppend = ftp.rename(fileName, newPath + "/" + fileName);
            logger.info("【修改ftp文件目录返回状态码】: {}", ftp.getReplyCode());
            if (isAppend) {
                logger.info("【修改ftp文件目录文件成功】,文件名: {}", fileName);
            }
            ftp.logout();
        } catch (Exception e) {
            logger.warn("【修改ftp文件目录异常】,文件名: {},异常堆栈:", fileName, e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.info(ioe.getMessage(), ioe);
                }
            }
        }
        return isAppend;
    }

    /**
     * 修改文件名
     *
     * @param oldFileName 原文件名
     * @param newFileName 新的文件名
     * @param filePath    文件夹路径
     * @return
     */
    public boolean renameFile(String oldFileName, String newFileName, String filePath) {
        boolean isAppend = false;
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            oldFileName = new String(oldFileName.getBytes(localCharset), SERVER_CHARSET);
            newFileName = new String(newFileName.getBytes(localCharset), SERVER_CHARSET);
            filePath = new String(filePath.getBytes(localCharset), SERVER_CHARSET);
            ftp.changeWorkingDirectory(filePath);
            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            isAppend = ftp.rename(oldFileName, newFileName);
            logger.info("【重命名ftp文件返回状态码】: {}", ftp.getReplyCode());
            logger.info("【修改ftp文件目录返回状态码】: {}", ftp.getReplyCode());
            if (isAppend) {
                logger.info("【重命ftp文件名成功】,旧文件名:{},新文件名: {}", oldFileName, newFileName);
            }
            ftp.logout();
        } catch (Exception e) {
            logger.warn("【重命ftp文件名失败】,异常堆栈:", e);
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.info(ioe.getMessage(), ioe);
                }
            }
        }
        return isAppend;
    }


    /**
     * 删除ftp 文件
     **/
    public boolean delete(String ftpPath, String fileName) {
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);

            ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
            fileName = new String(fileName.getBytes(localCharset), SERVER_CHARSET);

            ftp.changeWorkingDirectory(ftpPath);

            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            logger.info("【要删除的ftp文件名称】:{}", fileName);

            boolean deleted = ftp.deleteFile(fileName);
            if (deleted)
                logger.info("【删除ftp文件成功】,文件路径:{},文件名称:{}", ftpPath, fileName);
            else
                logger.warn("【删除ftp文件失败】,文件路径:{},文件名称:{}", ftpPath, fileName);

            ftp.logout();
            return deleted;
        } catch (Exception e) {
            logger.warn("【删除ftp文件异常】,文件路径:{},文件名称:{},异常堆栈:", ftpPath, fileName, e);
            return false;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
    }

    /**
     * 删除ftp 目录
     **/
    public boolean deleteDir(String ftpPath, String dirName) {
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return false;
            }
            ftp.setFileTransferMode(FTPClient.STREAM_TRANSFER_MODE);

            ftpPath = new String(ftpPath.getBytes(localCharset), SERVER_CHARSET);
            dirName = new String(dirName.getBytes(localCharset), SERVER_CHARSET);

            ftp.changeWorkingDirectory(ftpPath);

            logger.info("【当前ftp工作目录为】: {}", new String(ftp.printWorkingDirectory().getBytes(SERVER_CHARSET), localCharset));
            logger.info("【要删除的ftp目录】:{}", dirName);

            boolean deleted = ftp.removeDirectory(dirName);
            if (deleted)
                logger.info("【删除ftp目录成功】,文件路径:{},目录名称:{}", ftpPath, dirName);
            else
                logger.warn("【删除ftp目录失败】,文件路径:{},目录名称:{}", ftpPath, dirName);

            ftp.logout();
            return deleted;
        } catch (Exception e) {
            logger.warn("【删除ftp目录异常】,文件路径:{},目录名称:{},异常堆栈:", ftpPath, dirName, e);
            return false;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
    }

    /**
     * 获取ftp服务器上某个文件夹下的全部文件
     **/
    public FTPFile[] listFile(String ftpPath, FTPFileFilter ftpFileFilter) {
        try {
            boolean flag = getFtpClient();
            if (!flag) {
                return null;
            }
            ftp.changeWorkingDirectory(ftpPath);
            return ftp.listFiles(ftpPath, ftpFileFilter);
        } catch (Exception e) {
            logger.warn("【列举ftp目录异常】,文件路径:{},异常堆栈:", ftpPath, e);
            return null;
        } finally {
            if (ftp.isConnected()) {
                try {
                    ftp.disconnect();
                } catch (IOException ioe) {
                    logger.warn(ioe.getMessage(), ioe);
                }
            }
        }
    }

}

应用

1.向FTP服务器上传文件

  FtpUtil ftpUtil = new FtpUtil(cdmsWsapFtpProperties.getIp(),
   cdmsWsapFtpProperties.getPort(), 
   cdmsWsapFtpProperties.getUser(), 
   cdmsWsapFtpProperties.getPwd());


 File file =new File();
 String tempName = uploadFileName + ".now";
        boolean uploadOk = ftpUtil.uploadFile(cdmsWsapFtpProperties.getUploadDir(),
                tempName, uploadFileName, new BufferedInputStream(new FileInputStream(file)));
        if (uploadOk) {
            logger.info("文件【{}】上传到【{} {}】成功",uploadFileName, cdmsWsapFtpProperties.getIp(), cdmsWsapFtpProperties.getUploadDir());
            //id自增
            Long increment = redisUtil.increment(redisBatch);
            //更新t_personal_subscribe_wsap status 为 1
            updateStatus(wsapModelList);
        } else {
            logger.info("文件【{}】上传到【{} {}】失败",uploadFileName, cdmsWsapFtpProperties.getIp(), cdmsWsapFtpProperties.getUploadDir());
        }

2.修改文件路径

    private void moveFtpFile(String fileName) {
        try {
            FtpUtil ftpUtil = new FtpUtil(adaFtpFileProperties.getFtpIp(), adaFtpFileProperties.getFtpPort(), adaFtpFileProperties.getFtpUsername(), adaFtpFileProperties.getFtpPwd());
            boolean rename = ftpUtil.rename(adaFtpFileProperties.getFtpDir(), adaFtpFileProperties.getBackupDir(), fileName);
            if (rename) {
                log.info("将文件 {} 移动到备份目录 {} 成功", fileName, adaFtpFileProperties.getBackupDir());
            } else {
                log.warn("将文件 {} 移动到备份目录 {} 失败", fileName, adaFtpFileProperties.getBackupDir());
            }
        } catch (Exception e) {
            log.warn("移动文件异常", e);
        }
    }

3.删除ftp上的文件

 /**
     * 只保留最近15天的ftp文件
     **/
    private void doClearTmpFile() {
        logger.info("[对私客户信息] 删除本地文件3天前下载的文件开始");
        try {
            // 取当前文件名称的前缀
            final int domIndex = tdiipProperties.getTdiipFormat().indexOf(".");
            String startWith = tdiipProperties.getTdiipFormat().substring(0, domIndex);

            // ===============1. 删除ftp上的文件=================
            FtpUtil ftpUtil = new FtpUtil(tdiipProperties.getFtpIp(), tdiipProperties.getFtpPort(), tdiipProperties.getFtpUsername(), tdiipProperties.getFtpPwd());
            String targetPath = tdiipProperties.getBackupDir();
            LocalDate ftpBoundary = LocalDate.now().minusDays(DcdsFileConstants.SAVE_FILE_DAYS);
            final FTPFile[] ftpDeleteFiles = ftpUtil.listFile(targetPath, ftpFile -> {
                logger.info("[对私客户信息] ftp文件扫描开始,文件名:{}", ftpFile.getName());
                try {
                    int len = ftpFile.getName().length();
                    String dateString = ftpFile.getName().substring(len - 9, len - 1);
                    LocalDate fileDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
                    return ftpFile.getName().startsWith(startWith) && (fileDate.isBefore(ftpBoundary) || fileDate.isEqual(ftpBoundary));
                } catch (Exception ignore) {
                    return false;
                }
            });
            if (ftpDeleteFiles != null && ftpDeleteFiles.length > 0) {
                for (FTPFile file : ftpDeleteFiles) {
                    if (ftpUtil.delete(targetPath, file.getName())) {
                        logger.info("[对私客户信息] ftp文件删除成功,文件名:{}", file.getName());
                    } else {
                        logger.warn("[对私客户信息] ftp文件删除失败,文件名:{}", file.getName());
                    }
                }
            }

            // ===============2. 删除本地的文件=====================
            File localTmpDir = new File(tdiipProperties.getLocalTmpDir());
            if (!localTmpDir.exists())
                return;

            File[] files = null;
            if (localTmpDir.isDirectory()) {
                files = localTmpDir.listFiles();
            }
            if (files == null || files.length == 0)
                return;

            // 取删除日期的边界线
            LocalDate localBoundary = LocalDate.now();
            for (File file : files) {
                String fileName = file.getName();
                if (!fileName.startsWith(startWith))
                    continue;

                int len = file.getName().length();
                try {
                    String dateString = fileName.substring(len - 9, len - 1);
                    LocalDate fileDate = LocalDate.parse(dateString, DateTimeFormatter.ofPattern("yyyyMMdd"));
                    if ((fileDate.isBefore(localBoundary) || fileDate.isEqual(localBoundary)) && file.delete()) {
                        logger.info("[对私客户信息] 本地文件删除完成,文件名:{}", file.getName());
                    }
                } catch (Exception ignore) {
                    logger.warn("[对私客户信息] 本地文件删除失败,文件名:{}", file.getName());
                }
            }
        } catch (Exception e) {
            logger.error("[对私客户信息] 文件删除异常:", e);
        } finally {
            logger.info("[对私客户信息] 删除本地文件15天前下载的文件结束");
        }
    }
  • 4
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 当使用ftputil进行FTP操作时,可能会遇到“null”错误。这个错误通常是由于以下原因之一引起的: 1. FTP服务器连接问题:请确保你的FTP服务器地址、端口、用户名和密码正确。如果其中一个参数有误,可能会导致连接失败并返回“null”错误。请检查这些参数,并确保它们与你的FTP服务器设置匹配。 2. 文件/路径错误:如果你尝试访问一个不存在的文件或路径,也会导致“null”错误。请确保你要访问的文件/路径存在,并且你有足够的权限进行访问。 3. 网络问题:有时网络连接不稳定或中断可能导致FTP操作失败,并返回“null”错误。如果你的网络连接不稳定,请尝试使用稳定的网络连接再次运行操作。 4. 代码错误:在编写ftputil代码时,可能会有语法错误或逻辑错误导致“null”错误。请仔细检查你的代码,并确保它没有任何问题。如果发现问题,请进行适当的更正。 总结来说,ftputil报“null”错误可能是由于FTP服务器连接问题、文件/路径错误、网络问题或代码错误引起的。通过仔细检查和排除这些可能性,你应该能够找到并解决问题。 ### 回答2: 根据问题描述,在使用ftputil时遇到了"null"错误。"null"错误通常表示某个变量或对象的值为null,因此需要进一步检查具体的代码和错误提示以确定问题所在。 1. 首先,确保ftputil库已经正确安装,并且在代码中正确导入了该库。 2. 检查是否正确设置了FTP服务器的连接参数,包括主机地址、端口号、用户名和密码等。确保这些参数没有设置为null,而是正确设置为相应的值。 3. 如果使用的是Python 3.x版本,请检查代码中是否采用了正确的语法和函数调用。在Python 3.x中,某些函数的用法可能与之前的版本不同。 4. 检查代码中可能出现的其他错误。例如,在连接FTP服务器之前,可能需要先初始化ftputil库的某些配置;或者在上传或下载文件时,需要先检查本地文件是否存在于指定路径中。 5. 最后,查看具体的错误提示信息,尤其是报错的行数和具体的错误描述。这些信息能够提供更多的线索,帮助我们确定问题所在。 综上所述,要解决ftputil报"null"错误,需要检查代码中的配置参数、语法、函数调用以及其他潜在的错误,并仔细查看错误提示信息,找出具体的问题所在。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值