ftp工具

记录一个在项目中用到的ftp工具

1.ftp概述

  FTP 是File Transfer Protocol(文件传输协议)的英文简称,而中文简称为“文件传输协议”。用于Internet上的控制文件的双向传输。同时,它也是一个应用程序(Application)。基于不同的操作系统有不同的FTP应用程序,而所有这些应用程序都遵守同一种协议以传输文件。–摘自百度
  也就是说“ftp”是一种协议,用来在网络中传输文件,基于这种协议可以有一种应用:就是将文件从A处传输到B处,传输的过程是通过ftp协议完成的。
  实际的使用场景是这样的,会存在一个东西叫做FTP服务端,同时存在另一个东西叫做FTP客户端,显而易见,客户端与服务器端建立连接后,客户端可以向服务器端上传或下载文件,也可以进行一些其他操作,例如新建一个文件夹,或者删除一个文件。好啦,再举一个生动的例子:某人在上海出差,要向北京总部传一个word文件,于是他想到了使用ftp方式,打开他的电脑,再打开FTP客户端工具(本人使用FileZilla),连接到总部的FTP服务器,然后点击上传按钮,文件就上传了,于此同时他发现总部的FTP服务器中有最近上映的新电影(枪版),果断下载,看之,愉快的周末结束了。这大概就是一般情况下ftp的应用场景了。所以,这里面有两个概念很重要:FTP服务端,FTP客户端。
  windows系统下有许多FTP应用工具(本人使用FileZilla),使用这些工具可以很轻松的完成上述场景,但这不是本文讨论的重点,本文讨论的在java程序中如何对FTP服务端进行文件操作。

2.sftp概念

  这里还需要提一下sftp的概念:sftp是Secure File Transfer Protocol的缩写,安全文件传送协议。可以为传输文件提供一种安全的网络的加密方法。sftp 与 ftp 有着几乎一样的语法和功能。SFTP 为 SSH的其中一部分,是一种传输档案至 Blogger 伺服器的安全方式。–同样摘自百度。姑且就理解为一种比ftp更安全一点的协议吧。在windows下使用工具实现操作与ftp一样,本次代码实现同样需要考虑。

3.代码部分

  这段代码是在项目中抽象出来的一个工具类,形式为一个接口和两个实现类,接口定义了相关的文件操作方法,实现类分别是ftp的实现和sftp的实现。如下:

代码结构:

  1. IFtpHelper(ftp接口)
  2. SftpHelperImpl(sftp实现)
  3. StandardFtpHelperImpl(ftp实现)

具体代码:

IFtpHelper:
    import java.io.OutputStream;
    import java.util.Set;

    public interface IFtpHelper {

/**
 * 登陆ftp服务器(使用被动方式)
 * @param host
 * @param username
 * @param password
 * @param port
 * @param timeout
 */
public void loginFtpServer(String host, String username, String password, int port, int timeout);

/**
 *注销登陆
 */
public void logoutFtpServer();

/**
 * 创建目录(warn: 不支持递归创建)
 * @param directoryPath
 */
public void mkdir(String directoryPath);

/**
 * 递归创建目录
 * @param directoryPath
 */
public void mkDirRecursive(String directoryPath);

/**
 * 根据ftp服务器上指定目录下的文件名,获得其输出流
 * @param filePath
 * @return
 */
public OutputStream getOutputStream(String filePath);

public String getRemoteFileContent(String filePath);

public Set<String> getAllFilesInDir(String dir, String prefixFileName);

/**
 * 删除文件(不支持删除文件夹)
 * @param filesToDelete
 */
public void deleteFiles(Set<String> filesToDelete);

public void completePendingCommand();

/**
 * 向ftp目录中写入文件
 * @param sourceFilePath
 * @param targetFilePath
 */
public void localWriteToFtp(String sourceFilePath,String targetFilePath);

}
SftpHelperImpl:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.chinawiserv.dsp.dcs.dc.common.exception.DataXException;
import com.jcraft.jsch.*;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.commons.net.ftp.FTP;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Properties;
import java.util.Set;
import java.util.Vector;

public class SftpHelperImpl implements IFtpHelper {
private static final Logger LOG = LoggerFactory
        .getLogger(SftpHelperImpl.class);

private Session session = null;
private ChannelSftp channelSftp = null;

@Override
public void loginFtpServer(String host, String username, String password,
                           int port, int timeout) {
    JSch jsch = new JSch();
    try {
        this.session = jsch.getSession(username, host, port);
        if (this.session == null) {
            throw DataXException
                    .asDataXException(FtpWriterErrorCode.FAIL_LOGIN,
                            "创建ftp连接this.session失败,无法通过sftp与服务器建立链接,请检查主机名和用户名是否正确.");
        }

        this.session.setPassword(password);
        Properties config = new Properties();
        config.put("StrictHostKeyChecking", "no");
        // config.put("PreferredAuthentications", "password");
        this.session.setConfig(config);
        this.session.setTimeout(timeout);
        this.session.connect();

        this.channelSftp = (ChannelSftp) this.session.openChannel("sftp");
        this.channelSftp.connect();
    } catch (JSchException e) {
        if (null != e.getCause()) {
            String cause = e.getCause().toString();
            String unknownHostException = "java.net.UnknownHostException: "
                    + host;
            String illegalArgumentException = "java.lang.IllegalArgumentException: port out of range:"
                    + port;
            String wrongPort = "java.net.ConnectException: Connection refused";
            if (unknownHostException.equals(cause)) {
                String message = String
                        .format("请确认ftp服务器地址是否正确,无法连接到地址为: [%s] 的ftp服务器, errorMessage:%s",
                                host, e.getMessage());
                LOG.error(message);
                throw DataXException.asDataXException(
                        FtpWriterErrorCode.FAIL_LOGIN, message, e);
            } else if (illegalArgumentException.equals(cause)
                    || wrongPort.equals(cause)) {
                String message = String.format(
                        "请确认连接ftp服务器端口是否正确,错误的端口: [%s], errorMessage:%s",
                        port, e.getMessage());
                LOG.error(message);
                throw DataXException.asDataXException(
                        FtpWriterErrorCode.FAIL_LOGIN, message, e);
            }
        } else {
            String message = String
                    .format("与ftp服务器建立连接失败,请检查主机、用户名、密码是否正确, host:%s, port:%s, username:%s, errorMessage:%s",
                            host, port, username, e.getMessage());
            LOG.error(message);
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.FAIL_LOGIN, message);
        }
    }

}

@Override
public void logoutFtpServer() {
    if (this.channelSftp != null) {
        this.channelSftp.disconnect();
        this.channelSftp = null;
    }
    if (this.session != null) {
        this.session.disconnect();
        this.session = null;
    }
}

@Override
public void mkdir(String directoryPath) {
    boolean isDirExist = false;
    try {
        this.printWorkingDirectory();
        SftpATTRS sftpATTRS = this.channelSftp.lstat(directoryPath);
        isDirExist = sftpATTRS.isDir();
    } catch (SftpException e) {
        if (e.getMessage().toLowerCase().equals("no such file")) {
            LOG.warn(String.format(
                    "您的配置项path:[%s]不存在,将尝试进行目录创建, errorMessage:%s",
                    directoryPath, e.getMessage()), e);
            isDirExist = false;
        }
    }
    if (!isDirExist) {
        try {
            // warn 检查mkdir -p
            this.channelSftp.mkdir(directoryPath);
        } catch (SftpException e) {
            String message = String
                    .format("创建目录:%s时发生I/O异常,请确认与ftp服务器的连接正常,拥有目录创建权限, errorMessage:%s",
                            directoryPath, e.getMessage());
            LOG.error(message, e);
            throw DataXException
                    .asDataXException(
                            FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                            message, e);
        }
    }
}

@Override
public void mkDirRecursive(String directoryPath){
    boolean isDirExist = false;
    try {
        this.printWorkingDirectory();
        SftpATTRS sftpATTRS = this.channelSftp.lstat(directoryPath);
        isDirExist = sftpATTRS.isDir();
    } catch (SftpException e) {
        if (e.getMessage().toLowerCase().equals("no such file")) {
            LOG.warn(String.format(
                    "您的配置项path:[%s]不存在,将尝试进行目录创建, errorMessage:%s",
                    directoryPath, e.getMessage()), e);
            isDirExist = false;
        }
    }
    if (!isDirExist) {
        StringBuilder dirPath = new StringBuilder();
        dirPath.append(IOUtils.DIR_SEPARATOR_UNIX);
        String[] dirSplit = StringUtils.split(directoryPath, IOUtils.DIR_SEPARATOR_UNIX);
        try {
            // ftp server不支持递归创建目录,只能一级一级创建
            for(String dirName : dirSplit){
                dirPath.append(dirName);
                mkDirSingleHierarchy(dirPath.toString());
                dirPath.append(IOUtils.DIR_SEPARATOR_UNIX);
            }
        } catch (SftpException e) {
            String message = String
                    .format("创建目录:%s时发生I/O异常,请确认与ftp服务器的连接正常,拥有目录创建权限, errorMessage:%s",
                            directoryPath, e.getMessage());
            LOG.error(message, e);
            throw DataXException
                    .asDataXException(
                            FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                            message, e);
        }
    }
}

public boolean mkDirSingleHierarchy(String directoryPath) throws SftpException {
    boolean isDirExist = false;
    try {
        SftpATTRS sftpATTRS = this.channelSftp.lstat(directoryPath);
        isDirExist = sftpATTRS.isDir();
    } catch (SftpException e) {
        if(!isDirExist){
            LOG.info(String.format("正在逐级创建目录 [%s]",directoryPath));
            this.channelSftp.mkdir(directoryPath);
            return true;
        }
    }
    if(!isDirExist){
        LOG.info(String.format("正在逐级创建目录 [%s]",directoryPath));
        this.channelSftp.mkdir(directoryPath);
    }
    return true;
}

@Override
public OutputStream getOutputStream(String filePath) {
    try {
        this.printWorkingDirectory();
        String parentDir = filePath.substring(0,
                StringUtils.lastIndexOf(filePath, IOUtils.DIR_SEPARATOR));
        this.channelSftp.cd(parentDir);
        this.printWorkingDirectory();
        //对文件名进行拆分
        String fileName = filePath.substring(filePath.lastIndexOf(File.separator)+1);
        OutputStream writeOutputStream = this.channelSftp.put(fileName,
                ChannelSftp.APPEND);
        String message = String.format(
                "打开FTP文件[%s]获取写出流时出错,请确认文件%s有权限创建,有权限写出等", filePath,
                filePath);
        if (null == writeOutputStream) {
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.OPEN_FILE_ERROR, message);
        }
        return writeOutputStream;
    } catch (SftpException e) {
        String message = String.format(
                "写出文件[%s] 时出错,请确认文件%s有权限写出, errorMessage:%s", filePath,
                filePath, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.OPEN_FILE_ERROR, message);
    }
}

@Override
public String getRemoteFileContent(String filePath) {
    try {
        this.completePendingCommand();
        this.printWorkingDirectory();
        String parentDir = filePath.substring(0,
                StringUtils.lastIndexOf(filePath, IOUtils.DIR_SEPARATOR));
        this.channelSftp.cd(parentDir);
        this.printWorkingDirectory();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(22);
        this.channelSftp.get(filePath, outputStream);
        String result = outputStream.toString();
        IOUtils.closeQuietly(outputStream);
        return result;
    } catch (SftpException e) {
        String message = String.format(
                "写出文件[%s] 时出错,请确认文件%s有权限写出, errorMessage:%s", filePath,
                filePath, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.OPEN_FILE_ERROR, message);
    }
}

@Override
public Set<String> getAllFilesInDir(String dir, String prefixFileName) {
    Set<String> allFilesWithPointedPrefix = new HashSet<String>();
    try {
        this.printWorkingDirectory();
        @SuppressWarnings("rawtypes")
        Vector allFiles = this.channelSftp.ls(dir);
        LOG.debug(String.format("ls: %s", JSON.toJSONString(allFiles,
                SerializerFeature.UseSingleQuotes)));
        for (int i = 0; i < allFiles.size(); i++) {
            LsEntry le = (LsEntry) allFiles.get(i);
            String strName = le.getFilename();
            if (strName.startsWith(prefixFileName)) {
                allFilesWithPointedPrefix.add(strName);
            }
        }
    } catch (SftpException e) {
        String message = String
                .format("获取path:[%s] 下文件列表时发生I/O异常,请确认与ftp服务器的连接正常,拥有目录ls权限, errorMessage:%s",
                        dir, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
    return allFilesWithPointedPrefix;
}

@Override
public void deleteFiles(Set<String> filesToDelete) {
    String eachFile = null;
    try {
        this.printWorkingDirectory();
        for (String each : filesToDelete) {
            LOG.info(String.format("delete file [%s].", each));
            eachFile = each;
            this.channelSftp.rm(each);
        }
    } catch (SftpException e) {
        String message = String.format(
                "删除文件:[%s] 时发生异常,请确认指定文件有删除权限,以及网络交互正常, errorMessage:%s",
                eachFile, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
}

private void printWorkingDirectory() {
    try {
        LOG.info(String.format("current working directory:%s",
                this.channelSftp.pwd()));
    } catch (Exception e) {
        LOG.warn(String.format("printWorkingDirectory error:%s",
                e.getMessage()));
    }
}

@Override
public void completePendingCommand() {
}

/**
 * 向ftp目录中写入文件
 * @param sourceFilePath
 * @param targetFilePath
 */
@Override
public void localWriteToFtp(String sourceFilePath,String targetFilePath){
    try(BufferedOutputStream bos = new BufferedOutputStream( this.getOutputStream(targetFilePath));
    ) {
        Files.copy(Paths.get(sourceFilePath),bos);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

}
StandardFtpHelperImpl:
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.chinawiserv.dsp.dcs.dc.common.exception.DataXException;
import org.apache.commons.io.IOUtils;
import org.apache.commons.lang3.StringUtils;
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.FTPReply;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.*;
import java.net.UnknownHostException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.HashSet;
import java.util.Set;

public class StandardFtpHelperImpl implements IFtpHelper {
private static final Logger LOG = LoggerFactory
.getLogger(StandardFtpHelperImpl.class);
FTPClient ftpClient = null;

@Override
public void loginFtpServer(String host, String username, String password,
                           int port, int timeout) {
    this.ftpClient = new FTPClient();
    try {

// this.ftpClient.setControlEncoding(“UTF-8”);
// 不需要写死ftp server的OS TYPE,FTPClient getSystemType()方法会自动识别
// this.ftpClient.configure(new FTPClientConfig(FTPClientConfig.SYST_UNIX));
this.ftpClient.setDefaultTimeout(timeout);
this.ftpClient.setConnectTimeout(timeout);
this.ftpClient.setDataTimeout(timeout);

        // 连接登录
        this.ftpClient.connect(host, port);
        this.ftpClient.login(username, password);

        this.ftpClient.enterRemotePassiveMode();
        this.ftpClient.enterLocalPassiveMode();
        int reply = this.ftpClient.getReplyCode();
        if (!FTPReply.isPositiveCompletion(reply)) {
            this.ftpClient.disconnect();
            String message = String
                    .format("与ftp服务器建立连接失败,host:%s, port:%s, username:%s, replyCode:%s",
                            host, port, username, reply);
            LOG.error(message);
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.FAIL_LOGIN, message);
        }
        String fileEncoding = "GBK";
        if (FTPReply.isPositiveCompletion(ftpClient.sendCommand(
                "OPTS UTF8", "ON"))) {// 开启服务器对UTF-8的支持,如果服务器支持就用UTF-8编码,否则就使用本地编码(GBK).
            fileEncoding = "UTF-8";
        }
        this.ftpClient.setControlEncoding(fileEncoding);
    } catch (UnknownHostException e) {
        String message = String.format(
                "请确认ftp服务器地址是否正确,无法连接到地址为: [%s] 的ftp服务器, errorMessage:%s",
                host, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.FAIL_LOGIN, message, e);
    } catch (IllegalArgumentException e) {
        String message = String.format(
                "请确认连接ftp服务器端口是否正确,错误的端口: [%s], errorMessage:%s", port,
                e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.FAIL_LOGIN, message, e);
    } catch (Exception e) {
        String message = String
                .format("与ftp服务器建立连接失败,host:%s, port:%s, username:%s, errorMessage:%s",
                        host, port, username, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.FAIL_LOGIN, message, e);
    }

}

@Override
public void logoutFtpServer() {
    if (this.ftpClient.isConnected()) {
        try {
            this.ftpClient.logout();
        } catch (IOException e) {
            String message = String.format(
                    "与ftp服务器断开连接失败, errorMessage:%s", e.getMessage());
            LOG.error(message);
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.FAIL_DISCONNECT, message, e);
        } finally {
            if (this.ftpClient.isConnected()) {
                try {
                    this.ftpClient.disconnect();
                } catch (IOException e) {
                    String message = String.format(
                            "与ftp服务器断开连接失败, errorMessage:%s",
                            e.getMessage());
                    LOG.error(message);
                    throw DataXException.asDataXException(
                            FtpWriterErrorCode.FAIL_DISCONNECT, message, e);
                }
            }
            this.ftpClient = null;
        }
    }
}

@Override
public void mkdir(String directoryPath) {
    String message = String.format("创建目录:%s时发生异常,请确认与ftp服务器的连接正常,拥有目录创建权限",
            directoryPath);
    try {
        this.printWorkingDirectory();
        boolean isDirExist = this.ftpClient
                .changeWorkingDirectory(directoryPath);
        if (!isDirExist) {
            int replayCode = this.ftpClient.mkd(directoryPath);
            message = String
                    .format("%s,replayCode:%s", message, replayCode);
            if (replayCode != FTPReply.COMMAND_OK
                    && replayCode != FTPReply.PATHNAME_CREATED) {
                throw DataXException.asDataXException(
                        FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                        message);
            }
        }
    } catch (IOException e) {
        message = String.format("%s, errorMessage:%s", message,
                e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
}

@Override
public void mkDirRecursive(String directoryPath){
    StringBuilder dirPath = new StringBuilder();
    dirPath.append(IOUtils.DIR_SEPARATOR_UNIX);
    String[] dirSplit = StringUtils.split(directoryPath, IOUtils.DIR_SEPARATOR_UNIX);
    String message = String.format("创建目录:%s时发生异常,请确认与ftp服务器的连接正常,拥有目录创建权限", directoryPath);
    try {
        // ftp server不支持递归创建目录,只能一级一级创建
        for(String dirName : dirSplit){
            dirPath.append(dirName);
            boolean mkdirSuccess = mkDirSingleHierarchy(dirPath.toString());
            dirPath.append(IOUtils.DIR_SEPARATOR_UNIX);
            if(!mkdirSuccess){
                throw DataXException.asDataXException(
                        FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                        message);
            }
        }
    } catch (IOException e) {
        message = String.format("%s, errorMessage:%s", message,
                e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
}

public boolean mkDirSingleHierarchy(String directoryPath) throws IOException {
    boolean isDirExist = this.ftpClient
            .changeWorkingDirectory(directoryPath);
    // 如果directoryPath目录不存在,则创建
    if (!isDirExist) {
        int replayCode = this.ftpClient.mkd(directoryPath);
        if (replayCode != FTPReply.COMMAND_OK
                && replayCode != FTPReply.PATHNAME_CREATED) {
            return false;
        }
    }
    return true;
}

@Override
public OutputStream getOutputStream(String filePath) {
    try {
        this.printWorkingDirectory();
        String parentDir = filePath.substring(0,
                StringUtils.lastIndexOf(filePath, IOUtils.DIR_SEPARATOR));
        this.ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
        boolean flage = this.ftpClient.changeWorkingDirectory(parentDir);
        if(!flage){
            String message = String.format("请确认您的配置项path:[%s]存在,且配置的用户有权限进入", parentDir);
            LOG.error(message);
            throw DataXException.asDataXException(FtpWriterErrorCode.FILE_NOT_EXISTS, message);
        }
        this.printWorkingDirectory();
        OutputStream writeOutputStream = this.ftpClient
                .appendFileStream(new String(filePath.getBytes(), FTP.DEFAULT_CONTROL_ENCODING));
        String message = String.format(
                "打开FTP文件[%s]获取写出流时出错,请确认文件%s有权限创建,有权限写出等", filePath,
                filePath);
        if (null == writeOutputStream) {
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.OPEN_FILE_ERROR, message);
        }

        return writeOutputStream;
    } catch (IOException e) {
        String message = String.format(
                "写出文件 : [%s] 时出错,请确认文件:[%s]存在且配置的用户有权限写, errorMessage:%s",
                filePath, filePath, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.OPEN_FILE_ERROR, message);
    }
}

@Override
public String getRemoteFileContent(String filePath) {
    try {
        this.completePendingCommand();
        this.printWorkingDirectory();
        String parentDir = filePath.substring(0,
                StringUtils.lastIndexOf(filePath, IOUtils.DIR_SEPARATOR));
        this.ftpClient.changeWorkingDirectory(parentDir);
        this.printWorkingDirectory();
        ByteArrayOutputStream outputStream = new ByteArrayOutputStream(22);
        this.ftpClient.retrieveFile(filePath, outputStream);
        String result = outputStream.toString();
        IOUtils.closeQuietly(outputStream);
        return result;
    } catch (IOException e) {
        String message = String.format(
                "读取文件 : [%s] 时出错,请确认文件:[%s]存在且配置的用户有权限读取, errorMessage:%s",
                filePath, filePath, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.OPEN_FILE_ERROR, message);
    }
}

@Override
public Set<String> getAllFilesInDir(String dir, String prefixFileName) {
    Set<String> allFilesWithPointedPrefix = new HashSet<String>();
    try {
        boolean isDirExist = this.ftpClient.changeWorkingDirectory(dir);
        if (!isDirExist) {
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                    String.format("进入目录[%s]失败", dir));
        }
        this.printWorkingDirectory();
        FTPFile[] fs = this.ftpClient.listFiles(dir);
        // LOG.debug(JSON.toJSONString(this.ftpClient.listNames(dir)));
        LOG.debug(String.format("ls: %s",
                JSON.toJSONString(fs, SerializerFeature.UseSingleQuotes)));
        for (FTPFile ff : fs) {
            String strName = ff.getName();
            if (strName.startsWith(prefixFileName)) {
                allFilesWithPointedPrefix.add(strName);
            }
        }
    } catch (IOException e) {
        String message = String
                .format("获取path:[%s] 下文件列表时发生I/O异常,请确认与ftp服务器的连接正常,拥有目录ls权限, errorMessage:%s",
                        dir, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
    return allFilesWithPointedPrefix;
}

@Override
public void deleteFiles(Set<String> filesToDelete) {
    String eachFile = null;
    boolean deleteOk = false;
    try {
        this.printWorkingDirectory();
        for (String each : filesToDelete) {
            LOG.info(String.format("delete file [%s].", each));
            eachFile = each;
            deleteOk = this.ftpClient.deleteFile(each);
            if (!deleteOk) {
                String message = String.format(
                        "删除文件:[%s] 时失败,请确认指定文件有删除权限", eachFile);
                throw DataXException.asDataXException(
                        FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                        message);
            }
        }
    } catch (IOException e) {
        String message = String.format(
                "删除文件:[%s] 时发生异常,请确认指定文件有删除权限,以及网络交互正常, errorMessage:%s",
                eachFile, e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
}

private void printWorkingDirectory() {
    try {
        LOG.info(String.format("current working directory:%s",
                this.ftpClient.printWorkingDirectory()));
    } catch (Exception e) {
        LOG.warn(String.format("printWorkingDirectory error:%s",
                e.getMessage()));
    }
}

@Override
public void completePendingCommand() {
    /*
     * Q:After I perform a file transfer to the server,
     * printWorkingDirectory() returns null. A:You need to call
     * completePendingCommand() after transferring the file. wiki:
     * http://wiki.apache.org/commons/Net/FrequentlyAskedQuestions
     */
    try {
        boolean isOk = this.ftpClient.completePendingCommand();
        if (!isOk) {
            throw DataXException.asDataXException(
                    FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION,
                    "完成ftp completePendingCommand操作发生异常");
        }
    } catch (IOException e) {
        String message = String.format(
                "完成ftp completePendingCommand操作发生异常, errorMessage:%s",
                e.getMessage());
        LOG.error(message);
        throw DataXException.asDataXException(
                FtpWriterErrorCode.COMMAND_FTP_IO_EXCEPTION, message, e);
    }
}

/**
 * 向ftp目录中写入文件
 * @param sourceFilePath
 * @param targetFilePath
 */
@Override
public void localWriteToFtp(String sourceFilePath,String targetFilePath){
    try(BufferedOutputStream bos = new BufferedOutputStream(this.getOutputStream(targetFilePath));
    ) {
        Files.copy(Paths.get(sourceFilePath),bos);
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值