jsch通过SFTP查找特定文件

时间:2018-09-03 12:03:33

标签: java sftp jsch

我有Java应用程序通过SFTP连接到Linux。我正在使用jsch作为框架。现在,假设我需要重命名文件。

public boolean rename(String name) {
    boolean result = false;
    channelSftp = (ChannelSftp)channel;
    LsEntry currentFile = //here I have LsEntry object, pointing to specific record;

        logger.info("Renaming CRC file " + currentFile.getFilename() + " to " + name);
        try {
            //For the first parameter I get current position in the directory, then I append the filename of the currently processed file. 
            //For the first parameter I get current position in the directory, then I append the new name. 
            channel.rename(channel.pwd() + currentFile .getFilename(), channel.pwd() + name);


            result = true;

        } catch (Exception e) {
            logger.error("Error renaming crc file to " + name, e);
            result = false;

        }

    return result;
}

现在,在文件系统上重命名文件后,我还需要在正在使用的当前LsEntry对象中重命名该文件。问题在于LsEntry不提供这种方法,因此我必须再次加载它。现在我该如何寻找?我需要找到特定的文件,以便可以将其用作更新的LsEntry对象以供以后使用。那可能吗?

EDIT1:

代表文件系统上的条目的LsEntry对象必须以某种方式创建,我可以通过将向量对象转换为对象来实现。像这样:

    System.out.println("searching for files in following  directory" + directory);
    channelSftp.cd(directory);
    Vector foundFiles = channelSftp.ls(directory);


     for(int i=2; i<foundFiles.size();i++){

            LsEntry files = (LsEntry) foundFiles.get(i);
            System.out.println("found file: " + files.getFilename());
            System.out.println("Found file with details : " + files.getLongname());
            System.out.println("Found file on path: " + channelSftp.pwd());

            channelSftp.rename(channelSftp.pwd() + files.getFilename(), channelSftp.pwd() + "picovina");

            //LsEntry has now old name.             

1 个答案:

答案 0 :(得分:1)

public class SftpClient {

    private final JSch jSch;

    private Session session;
    private ChannelSftp channelSftp;
    private boolean connected;

    public SftpClient() { this.jSch = new JSch(); }

    public void connect(final ConnectionDetails details) throws ConnectionException {
        try {
            if (details.usesDefaultPort()) {
                session = jSch.getSession(details.getUserName(), details.getHost());
            } else {
                session = jSch.getSession(details.getUserName(), details.getHost(), details.getPort());
            }
            channelSftp = createSftp(session, details.getPassword());
            channelSftp.connect();

            connected = session.isConnected();
        } catch (JSchException e) {
            throw new ConnectionException(e.getMessage());
        }
    }

    public void disconnect() {
        if (connected) {
            channelSftp.disconnect();
            session.disconnect();
        }
    }

    public void cd(final String path) throws FileActionException {
        try {
            channelSftp.cd(path);
        } catch (SftpException e) {
            throw new FileActionException(e.getMessage());
        }
    }

    public List<FileWrapper> list() throws FileActionException {
        try {
            return collectToWrapperList(channelSftp.ls("*"));
        } catch (SftpException e) {
            throw new FileActionException(e.getMessage());
        }
    }

    public String pwd() throws FileActionException {
        try {
            return channelSftp.pwd();
        } catch (SftpException e) {
            throw new FileActionException(e.getMessage());
        }
    }

    public boolean rename(final FileWrapper wrapper, final String newFileName) throws FileActionException {
        try {
            String currentPath = channelSftp.pwd();
            channelSftp.rename(currentPath + wrapper.getFileName(), currentPath + newFileName);
        } catch (SftpException e) {
            throw new FileActionException(e.getMessage());
        }
        return true;
    }

    private List<FileWrapper> collectToWrapperList(Vector<ChannelSftp.LsEntry> entries) {
        return entries.stream()
        .filter(entry -> !entry.getAttrs().isDir())
        .map(entry -> FileWrapper.from(entry.getAttrs().getMtimeString(), entry.getFilename(), entry.getAttrs().getSize()))
        .collect(Collectors.toList());
    }

    private ChannelSftp createSftp(final Session session, final String password) throws JSchException {
        session.setPassword(password);
        Properties properties = new Properties();
        properties.setProperty("StrictHostKeyChecking", "no");
        session.setConfig(properties);
        session.connect();

    return (ChannelSftp) session.openChannel("sftp");
    }
}

请注意,list方法有效地返回了FileWrapper个对象而不是LsEntry个对象的列表。

public class FileWrapper {

    private static final String TIME_FORMAT = "EEE MMM dd HH:mm:ss zzz yyyy";

    private Date timeStamp;
    public Date getTimeStamp() { return timeStamp; }

    private String fileName;
    public String getFileName() { return fileName; }

    private Long fileSize;
    public Long getFileSize() { return fileSize; }

    private FileWrapper(String timeStamp, String fileName, Long fileSize) throws ParseException {
    this.timeStamp = new SimpleDateFormat(TIME_FORMAT).parse(timeStamp);
    this.fileName = fileName;
    this.fileSize = fileSize;
    }

    public static FileWrapper from(final String timeStamp, final String fileName, final Long fileSize) {
    try {
        return new FileWrapper(timeStamp, fileName, fileSize);
    } catch (ParseException e) {
        e.printStackTrace();
    }
    return null;
    }

}

使用此功能,您可以轻松列出远程目录并获取所有文件的属性。

您只需调用SftpClient#rename并重命名所需的文件即可。

我知道您想避免重构,但是鉴于其非常严格的性质或LsEntry以及该库仍使用Vector这样的事实,我想这是最好的方法去(将来会避免头痛)。

我知道这可能不是您期望的答案的100%,但我认为这将对您有所帮助。