JSCH найти определенный файл через SFTP - PullRequest
0 голосов
/ 03 сентября 2018

У меня есть приложение Java, подключающееся к Linux через SFTP. Я использую 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 для дальнейшего использования. Это возможно?

РЕДАКТИРОВАТЬ1:

Объект 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 голосов
/ 03 сентября 2018
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% ответ, который вы ожидаете, но я думаю, что это будет полезно для вас.

...