FtpClient获取数据实例

实际项目中有一个需求:将远程服务器上的文件转存到本地服务器,开发中遇到很多问题,总结出一个可行的代码实例。

 使用ftpClient进行文件转存,遇到很多问题:

1.retrieveFileStream获取到文件流经常是空的

2.使用completePendingCommand()经常使程序死掉

为了解决上述问题,贴出我的代码,以供参考:

 FTPClient初始化:

package com.aaa.ftpservice.entity;

import lombok.Data;

@Data
public class FtpInfoEntity {
    private Long id;

    private String code;

    private Short isSsl;

    private Boolean isTls;

    private String username;

    private String password;

    private String host;

    private Integer port;

    private Object pwdEnc;

}
import org.apache.commons.net.ftp.FTP;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPClientConfig;
import org.apache.commons.net.ftp.FTPReply;
import org.apache.commons.net.ftp.FTPSClient;

//method
public FTPClient getClient(FtpInfoEntity ftpInfoEntity)
    {
        FTPClient ftpClient = null;
        try {
            if (ftpInfoEntity.getIsTls()) {
                ftpClient = new FTPSClient(true);
            }
            else {
                ftpClient = new FTPClient();
            }
            ftpClient.setDataTimeout(600000);       //设置传输超时时间为10分钟
            ftpClient.setConnectTimeout(600000);       //连接超时为10分钟
            log.info("connect start, ftpInfoEntity is {}", ftpInfoEntity.toString());
            ftpClient.connect(ftpInfoEntity.getHost(), ftpInfoEntity.getPort());
            ftpClient.login(ftpInfoEntity.getUsername(), ftpInfoEntity.getPassword());
            if (ftpClient instanceof FTPSClient) {
                ((FTPSClient) ftpClient).execPROT("P");
                ((FTPSClient) ftpClient).execPBSZ(0);
            }

            ftpClient.enterLocalPassiveMode();//开启被动模式,每次数据连接之前ftp client告诉ftp server开通 一个端口来传输数据。
            ftpClient.setFileTransferMode(FTP.STREAM_TRANSFER_MODE);
            ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
            FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_UNIX);
            ftpClient.configure(conf);
            int reply = ftpClient.getReplyCode();
            log.info("connect reply is {}", reply);
            if (!FTPReply.isPositiveCompletion(reply)) {
                ftpClient.disconnect();
                log.error("FTP连接错误...");
                return null;
            }

        } catch (Exception e) {
            log.error("---connect error {}", e.getMessage());
        }

        return ftpClient;
    }

下载文件

//removeFile: d56a4ed296d311ecb6160242ac14001e/2022/08/18/b4eff63f-b0a2-4b91-a757-de0c9931e018/CCD/b05f1a66-9c6e-4a63-8a39-191c7b01c8f2.jpg
public byte[] download(FTPClient ftpClient,String remoteFile)
    {
        byte[] data = null; 
        InputStream is = null;  
        try {
            int remoteDirIdx = remoteFile.lastIndexOf("/");
            String remoteDir = remoteFile.substring(0, remoteDirIdx);
            String remoteFileName = remoteFile.substring(remoteDirIdx + 1);
       
            //这句话一定要加!!!!!!
            //因为changeWorkingDirectory是根据当前的ftp路径来进行切换的,所以如果传入的removeDir绝对路径,那么一定要先把当前路径切换到根路径,再切换到removeDir,否则会找到不到文件
            ftpClient.changeWorkingDirectory("/");
            //这句话一定要加!!!!!!

            boolean b = ftpClient.changeWorkingDirectory(remoteDir);

            int length = ftpClient.listNames(remoteFileName).length;
            if (length == 0) {
                log.info("---remoteFile is not exist");
                return null;
            }

            is = ftpClient.retrieveFileStream(remoteFileName);
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int num = is.read(buffer);
            while (num != -1) {
                baos.write(buffer, 0, num);
                num = is.read(buffer);
            }
            baos.flush();
            data = baos.toByteArray();
            return data;
        } catch (Exception e) {
            log.error("---FTPUtil download1 e111 , {}  ", e.getMessage());
        } finally {
            try { 
                if (Objects.nonNull(is)) {
                    is.close();
                    ftpClient.completePendingCommand();
                }
            } catch (Exception e1) {
                log.error("---FTPUtil download1 e222 , {} ", e1.getCause());
            }
        }
        return data;
    }

保存到本地:

private void saveFileToLocal(byte[] data, String oldFilePath) throws IOException
    { 
        FileOutputStream fileOutputStream = null;
        InputStream inputStream = null;
        File tempFile = null;
        try {
            int remoteDirIdx = oldFilePath.lastIndexOf("/");
            String remoteDir = oldFilePath.substring(0, remoteDirIdx);
            String remoteFileName = oldFilePath.substring(remoteDirIdx + 1);
            String newFilePath = "/home/aaa/"+ remoteDir;
            tempFile = new File(newFilePath);
            if (!tempFile.exists()) {
                tempFile.mkdirs();
            }
            inputStream = new ByteArrayInputStream(data);
            String fileName = tempFile.getPath() + File.separator + remoteFileName;
            fileOutputStream = new FileOutputStream(fileName);
            // 数据缓冲
            byte[] buffer = new byte[1024 * 1024];
            //读取到的数据长度
            int len;
            // 开始读取
            while ((len = inputStream.read(buffer)) != -1) {
                fileOutputStream.write(buffer, 0, len);
            }
        } catch (Exception e) {
            log.error("----ftp saveFileToLocal error, {}", e.getMessage());
        } finally {
            log.info("----ftp saveFileToLocal success,{}", oldFilePath);
            fileSaveDao.deleteByPrimaryKey(fileSaveId);
            if (Objects.nonNull(fileOutputStream)) {
                fileOutputStream.close();
            }
            if (Objects.nonNull(inputStream)) {
                inputStream.close();
            }
            if (Objects.nonNull(tempFile)) {
                tempFile.delete();
            }
        }
    }

以上为我的代码实现,以供参考

----2022.11.28分割线----

在功能测试的时候,我把保存文件的文件名添加了随机数作为后缀,导致系统上保存了一些不规则的图片文件,类似于下面的这样

111.jpg1234,111.jpg1235,111.jpg1236。

为了将这些图片的文件名改成正常的xxx.jpg文件名,我使用下面的命令行来完成。

find . -name "*.jpg*" -type f ! -name "*.jpg" -exec sh -c 'f="{}"; mv -- "$f" "${f%.jpg*}.jpg"' \;

其中:

find . -name "*.jpg*" -type f ! -name "*.jpg"     ---  查找出当前目录下所有  "xxx.jpgxxx"格式名称,但不是 "xxxx.jpg" 的文件

-exec sh -c 'f="{}"; mv -- "$f" "${f%.jpg*}.jpg"' \;   ---  将 "xxx.jpgxxx"格式名称的文件重命名位"xxxx.jpg"

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

高考我军

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

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

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

打赏作者

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

抵扣说明:

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

余额充值