SpringBoot-FTP操作

SpringBoot-FTP操作


@Slf4j
@Component
public class FtpUtil implements CommandLineRunner {

    /**
     * 连接断开
     */
    private static int ftpPort = 21;

    /**
     * 主机地址
     */
    private static String ftpHost = "192.168.0.117";

    /**
     * 用户名
     */
    private static String ftpUsername = "zht";

    /**
     * 密码
     */
    private static String ftpPassword = "123456";

    @Autowired(required = false)
    private BaseSysParamService baseSysParamService;

    public FTPClient ftpClient = null;

    public boolean trayAgeain = false;

    /**
     * 线程池
     */
    @Qualifier("otherDateBaseExecutor")
    @Autowired
    private TaskExecutor taskExecutor;

    @Override
    public void run(String... args) throws Exception {
        CompletableFuture.runAsync(() ->{
            setParam();
            getFtpClient();
        }, taskExecutor);
    }

    /**
     * 设置参数
     */
    public void setParam() {
        CompletableFuture.runAsync(() ->{
            String otherFtpServer = baseSysParamService.getValByName("pers.otherFtpServer");
            if (StringUtils.isNotEmpty(otherFtpServer)) {
                String[] serverPort = otherFtpServer.split(":");
                if (serverPort.length >= 2) {
                    ftpPort = Optional.ofNullable(serverPort[1]).filter(StringUtils::isNotEmpty).map(Integer::parseInt).orElse(ftpPort);
                    ftpHost = Optional.ofNullable(serverPort[0]).filter(StringUtils::isNotEmpty).orElse(ftpHost);
                }
            }
            String otherFtpUser = baseSysParamService.getValByName("pers.otherFtpUser");
            ftpUsername = Optional.ofNullable(otherFtpUser).filter(StringUtils::isNotEmpty).orElse(ftpUsername);
            String otherFtpPass = baseSysParamService.getValByName("pers.otherFtpPass");
            ftpPassword = Optional.ofNullable(otherFtpPass).filter(StringUtils::isNotEmpty).orElse(ftpPassword);
        }, taskExecutor);
    }

    /**
     * 初始化ftp
     *
     * @return ftpClient
     */
    public FTPClient initFtpClient() {
        close();
        try {
            ftpClient = new FTPClient();
            //设置连接超时时间
            ftpClient.setConnectTimeout(1000 * 30);
            //设置ftp字符集
            ftpClient.setControlEncoding("utf-8");
            ftpClient.setDefaultPort(ftpPort);
            ftpClient.connect(ftpHost, ftpPort);
            ftpClient.login(ftpUsername, ftpPassword);
            ftpClient.enterLocalPassiveMode();// 设置被动模式
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);//设置二进制传输
            int replyCode = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(replyCode)) {
                close();
                log.error("未连接到FTP,用户名或密码错误!");
                OtherFtpServiceImpl.addMessage("未连接到FTP,用户名或密码错误!");
                return null;
            } else {
                log.info("FTP连接成功!");
                return ftpClient;
            }
        } catch (SocketException socketException) {
            log.error("FTP的IP地址可能错误,请正确配置!");
            OtherFtpServiceImpl.addMessage("FTP的IP地址可能错误,请正确配置!");
            return null;
        } catch (IOException ioException) {
            ioException.printStackTrace();
            log.error("FTP的端口错误,请正确配置!");
            OtherFtpServiceImpl.addMessage("FTP的端口错误,请正确配置!");
            return null;
        }
    }

    /**
     * 关闭连接
     */
    public void close() {
        if (ObjectUtils.isNotEmpty(ftpClient)) {
            try {
                //logout();
                ftpClient.disconnect();
                ftpClient = null;
            } catch (IOException e) {
                e.printStackTrace();
                log.info("关闭ftp异常");
            }
        }
    }

    /**
     * 获取连接客户端
     *
     * @return 客户端
     */
    public FTPClient getFtpClient() {
        if (ObjectUtils.isEmpty(ftpClient) || !ftpClient.isConnected() || !FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
            initFtpClient();
            if (ObjectUtils.isEmpty(ftpClient)) {
                CompletableFuture.runAsync(this::tryGetFtpClient, taskExecutor);
            }
        }
        return ftpClient;
    }

    /**
     * 尝试连接
     */
    private synchronized void tryGetFtpClient() {
        // 正在重试中
        if (!trayAgeain) {
            trayAgeain = true;
            int max = 4;
            int count = 0;
            while (count < max) {
                initFtpClient();
                if (ObjectUtils.isNotEmpty(ftpClient) && ftpClient.isConnected()) {
                    break;
                }
                try {
                    log.info("连接ftp失败,将在10s后进行第 {} 次重试!", count);
                    OtherFtpServiceImpl.addMessage("连接ftp失败,将在10s后进行第 ").append(count).append(" 次重试!");
                    Thread.sleep(10000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                count++;
            }
            trayAgeain = false;
        }
    }

    public static void main(String[] args) {
        OtherFtpService otherFtpService = new OtherFtpServiceImpl();
        otherFtpService.readPerFile("test.txt", "/test");
    }

    /**
     * 登录退出
     */
    public void logout() {
        try {
            if (ObjectUtils.isNotEmpty(ftpClient)) {
                ftpClient.logout();
            }
        } catch (IOException e) {
            log.info("登录退出失败!{}", e.getMessage());
            e.printStackTrace();
        }
    }

    /**
     * 关闭输入流
     *
     * @param inputStream 输入流
     */
    public void closeInputStream(InputStream inputStream) {
        if (inputStream != null) {
            try {
                inputStream.close();
            } catch (IOException e) {
                log.error("关闭流失败 -------- {}", e.getMessage());
            }
        }
    }

    /**
     * 改变目录路径
     *
     * @param directory 目录
     * @return
     */
    public FTPClient changeWorkingDirectory(String directory) {
        try {
            getFtpClient();
            if (ObjectUtils.isNotEmpty(ftpClient)) {
                boolean flag = ftpClient.changeWorkingDirectory(directory);
                if (flag) {
                    log.info("进入文件夹" + directory + " 成功!");
                } else {
                    log.info("进入文件夹" + directory + " 失败!");
                    OtherFtpServiceImpl.addMessage("进入文件夹" + directory + " 失败!");
                }
            }
        } catch (IOException e) {
            log.info("改变ftp目录失败!{}", e.getMessage());
            OtherFtpServiceImpl.addMessage("改变ftp目录失败!" + e.getMessage());
            CompletableFuture.runAsync(this::tryGetFtpClient, taskExecutor);
        }
        return ftpClient;
    }

    /**
     * 获取文件的 base64
     *
     * @param remoteFileName 文件名
     * @param remoteDir      文件目录
     * @return 文件的 base64
     */
    public String readFileToBase64(String remoteFileName, String remoteDir) {
        String base64 = "";
        InputStream inputStream = null;

        try {
            FTPClient ftpClient = changeWorkingDirectory(remoteDir);
            if (ObjectUtils.isEmpty(ftpClient)) {
                return null;
            }
            FTPFile[] ftpFiles = ftpClient.listFiles(remoteDir);
            boolean flag = false;
            //遍历当前目录下的文件,判断要读取的文件是否在当前目录下
            for (FTPFile ftpFile : ftpFiles) {
                String name = new String(ftpFile.getName().getBytes(StandardCharsets.ISO_8859_1), StandardCharsets.UTF_8);
                if (remoteFileName.equals(name)) {
                    flag = true;
                    break;
                }
            }

            if (!flag) {
                log.error("目录:{} 下没有 {}", remoteDir, remoteFileName);
                OtherFtpServiceImpl.addMessage("目录:").append(remoteDir).append(" 下没有 ").append(remoteFileName);
                OtherFtpServiceImpl.addDeptMessage("目录:", true).append(remoteDir).append(" 下没有 ").append(remoteFileName);
                return null;
            }
            String filePath = remoteDir + File.separator +remoteFileName;
            //获取待读文件输入流
            inputStream = ftpClient.retrieveFileStream(filePath);
            if (ObjectUtils.isNotEmpty(inputStream)) {
                //inputStream.available() 获取返回在不阻塞的情况下能读取的字节数,正常情况是文件的大小
                Thread.sleep(1000);
                byte[] bytes = new byte[inputStream.available()];
                //将文件数据读到字节数组中
                inputStream.read(bytes);
                base64 = Base64Util.encode(bytes);
                log.info("读取文件 {} 成功!", remoteFileName);
            }else {
                log.info("读取文件 {} 失败!path: {}", remoteFileName, filePath);
                OtherFtpServiceImpl.addMessage("读取文件 ").append(remoteFileName).append(" 失败!path: ").append(filePath);
            }
        } catch (IOException | InterruptedException e) {
            log.error("读取文件失败 ----->>> {}", e.getMessage());
            OtherFtpServiceImpl.addMessage("读取文件 ").append(remoteFileName).append(" 失败!");
            return null;
        } finally {
            closeInputStream(inputStream);
        }

        return base64;
    }

    /**
     * 上传文件
     *
     * @param inputStream 待上传文件的输入流
     * @param originName  文件保存时的名字
     * @param remoteDir   文件要存放的目录
     */
    public boolean uploadFile(InputStream inputStream, String originName, String remoteDir) {
        try {
            //进入到文件保存的目录
            FTPClient ftpClient = changeWorkingDirectory(remoteDir);
            if (ObjectUtils.isEmpty(ftpClient)) {
                return false;
            }
            boolean isSuccess = ftpClient.storeFile(originName, inputStream);//保存文件
            if (isSuccess) {
                log.info("{}---》上传成功!", originName);
            } else {
                log.info("{}---》上传失败!", originName);
            }
            return isSuccess;
        } catch (IOException e) {
            log.info("{}---》上传失败!", originName);
            return false;
        }
    }

    /**
     * 下载文件
     *
     * @param remoteDir      远程目录
     * @param remoteFileName 远程目录下的文件
     * @param outputStream   输出流
     */
    public void download(String remoteDir, String remoteFileName, OutputStream outputStream) {
        InputStream inputStream = null;
        try {
            //进入到文件保存的目录
            FTPClient ftpClient = changeWorkingDirectory(remoteDir);
            FTPFile[] ftpFiles = ftpClient.listFiles();
            if (ftpFiles != null && ftpFiles.length > 0) {
                for (FTPFile ftpFile : ftpFiles) {
                    //防止乱码
                    if (StringUtils.equals(ftpFile.getName(), remoteFileName)) {
                        ftpClient.retrieveFile(ftpFile.getName(), outputStream);
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 删除文件信息
     *
     * @param remoteDir
     * @param fileName
     */
    public void deleteFile(String remoteDir, String fileName) {
        //进入到文件保存的目录
        FTPClient ftpClient = changeWorkingDirectory(remoteDir);
        if (ObjectUtils.isNotEmpty(ftpClient)) {
            try {
                ftpClient.deleteFile(fileName);
            } catch (IOException e) {
                e.printStackTrace();
                log.info("删除路径 {} 下文件 {} 失败!", remoteDir, fileName);
            }
        }
    }
}


  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值