为什么JSch ChannelSftp返回"处理已关闭"?

时间:2017-10-25 07:07:27

标签: java sftp jsch

我正在使用jsch 0.1.54,我试图通过SFTP访问FTP服务器。这一切都正常工作,我可以步入所需的目录,但当我使用模式执行文件 channel.ls(" *"); 我只能得到第一场比赛,下一场比赛我得到 "处理关闭 "但不是文件名。为什么呢?

更确切地说,当我最终到达所需的目录时,我做了一个

sftp.ls(ftpAccount + File.separator + lsEntry.getFilename() +
                                        File.separator + "*", new ChannelSftp.LsEntrySelector() {...});

也许LsEntrySelectore是" Handle关闭" 的原因!?

以下是该方法的完整代码:

   public Map<String, byte[]> readFiles () {
    final Map<String, byte[]> vaFiles = new HashMap();
    final Channel channel;
    try {
        channel = session.openChannel("sftp");
        channel.connect();
        final List<String> ftpAccounts = Arrays.stream(this.ftpAccounts).collect(Collectors.toList());
        for (final String ftpAccount : ftpAccounts) {
            System.out.println(ftpAccount);
            try {
                try {
                    final SftpATTRS attrs = sftp.stat(ftpAccount + File.separator + XXX_DIR);
                } catch (Exception e) {
                    // The folder ftpAccount + File.separator + XXX_DIR does not exist.
                    // Simply continue...
                    continue;
                }
                final Vector<ChannelSftp.LsEntry> files = sftp.ls(ftpAccount + File.separator + "*");
                final List<ChannelSftp.LsEntry> ftpFileList = files.stream().collect(Collectors.toList());
                for (final ChannelSftp.LsEntry lsEntry : ftpFileList) {
                    if (lsEntry.getAttrs().isDir() &&
                        lsEntry.getFilename().equals(XXX_DIR)) {
                            sftp.ls(ftpAccount + File.separator + lsEntry.getFilename() +
                                    File.separator + "*", new ChannelSftp.LsEntrySelector() {

                                @Override
                                public int select (final ChannelSftp.LsEntry entry) {
                                    final Matcher mtc = pattern.matcher(entry.getFilename());
                                    final SftpATTRS attr = entry.getAttrs();
                                    if (mtc.find() && !attr.isDir() && !attr.isLink()) {
                                        System.out.println(entry.getFilename());
                                        try {
                                            final ByteArrayOutputStream baos = new
                                                                                       ByteArrayOutputStream();
                                            sftp.get(ftpAccount + File.separator +
                                                     XXX_DIR + File.separator + entry.getFilename(), baos);
                                            vaFiles.put(ftpAccount + File.separator +
                                                        XXX_DIR + File.separator + entry.getFilename(),
                                                    baos.toByteArray());
                                            logger.info("File " + ftpAccount + File.separator +
                                                        XXX_DIR + File.separator + entry.getFilename() + " downloaded.");
                                            baos.close();
                                        } catch (IOException e) {
                                            e.printStackTrace();
                                        } catch (SftpException e) {
                                            e.printStackTrace();
                                        }
                                    }
                                    System.out.println("CONTINUE = " + CONTINUE);
                                    return CONTINUE;
                                }
                          });
                    }//end if
                }
            } catch (SftpException e) {
                e.printStackTrace();
            }
            break;
        }
    } catch (JSchException e) {
        e.printStackTrace();
    }

    return vaFiles;
}

这是我打开和关闭ByteArrayOutputStream的方式吗?

例外:

4: 
    at com.jcraft.jsch.ChannelSftp.ls(ChannelSftp.java:1747)
    at de.postcon.SftpFileHandler.readFiles(SftpFileHandler.java:150)
    at de.postcon.VaFtp2EmMover.downloadVAFiles(VaFtp2EmMover.java:145)
    at de.postcon.VaFtp2EmMover.main(VaFtp2EmMover.java:84)
Caused by: java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at com.jcraft.jsch.Buffer.getByte(Buffer.java:148)
    at com.jcraft.jsch.Buffer.getString(Buffer.java:188)
    at com.jcraft.jsch.ChannelSftp.ls(ChannelSftp.java:1675)
    ... 3 more

将方法代码最小化为:

public Map<String, byte[]> readFiles () {
    final Map<String, byte[]> vaFiles = new HashMap();
    final String ftpAccount = "/accumio";
    try {
        sftp.ls(ftpAccount + File.separator + TO_POSTCON_DIR + File.separator + "*", new ChannelSftp.LsEntrySelector() {

            @Override
            public int select (final ChannelSftp.LsEntry entry) {
                final Matcher mtc = pattern.matcher(entry.getFilename());
                final SftpATTRS attr = entry.getAttrs();
                if (mtc.find() && !attr.isDir() && !attr.isLink()) {
                    System.out.println(entry.getFilename());
                }
                System.out.println("CONTINUE = " + CONTINUE);
                return CONTINUE;
            }
        });
    } catch (SftpException e) {
        e.printStackTrace();
    }

    return vaFiles;
}

......它在工作。因此,问题似乎是由 sftp.get(...); 产生的,因为当我把这一行放在

final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        sftp.get(ftpAccount + File.separator + XXX_DIR + File.separator + entry.getFilename(), baos);

System.out.println(entry.getFilename()); 之后再次出现,我得到以下ArrayIndexOutOfBoundsException:

4: 
    at com.jcraft.jsch.ChannelSftp.ls(ChannelSftp.java:1747)
    at de.postcon.SftpFileHandler.readFiles(SftpFileHandler.java:129)
    at de.postcon.VaFtp2EmMover.downloadVAFiles(VaFtp2EmMover.java:145)
    at de.postcon.VaFtp2EmMover.main(VaFtp2EmMover.java:84)
Caused by: java.lang.ArrayIndexOutOfBoundsException
    at java.lang.System.arraycopy(Native Method)
    at com.jcraft.jsch.Buffer.getByte(Buffer.java:148)
    at com.jcraft.jsch.Buffer.getString(Buffer.java:188)
    at com.jcraft.jsch.ChannelSftp.ls(ChannelSftp.java:1675)
    ... 3 more

解决方案:

public Map<String, byte[]> readFiles () {
    final Map<String, byte[]> vaFiles = new HashMap();
    final Channel channel;
    try {
        channel = session.openChannel("sftp");
        channel.connect();
        final List<String> ftpAccounts = Arrays.stream(this.ftpAccounts).collect(Collectors.toList());
//            final List<String> ftpFiles = new ArrayList<>();
        for (final String ftpAccount : ftpAccounts) {
//                System.out.println(ftpAccount);
            try {
                try {
                    final SftpATTRS attrs = sftp.stat(ftpAccount + File.separator + XXX_DIR);
                } catch (Exception e) {
                    // The folder ftpAccount + File.separator + XXX_DIR does not exist.
                    // Simply continue...
                    continue;
                }
                final Vector<ChannelSftp.LsEntry> files = sftp.ls(ftpAccount + File.separator + "*");
                final List<ChannelSftp.LsEntry> ftpFileList = files.stream().collect(Collectors.toList());
                final List<ChannelSftp.LsEntry> entries = new ArrayList();
                for (final ChannelSftp.LsEntry lsEntry : ftpFileList) {
                    if (lsEntry.getAttrs().isDir() &&
                        lsEntry.getFilename().equals(XXX_DIR)) {
                            sftp.ls(ftpAccount + File.separator + lsEntry.getFilename() +
                                    File.separator + "*", new ChannelSftp.LsEntrySelector() {

                                @Override
                                public int select (final ChannelSftp.LsEntry entry) {
                                    final Matcher mtc = pattern.matcher(entry.getFilename());
                                    final SftpATTRS attr = entry.getAttrs();
                                    if (mtc.find() && !attr.isDir() && !attr.isLink()) {
                                        // gather the files to be read...
                                        entries.add(entry);
                                    }
                                    return CONTINUE;
                                }
                            });
                    }//end if
                }//end for lsEntry

                // store the gathered files...
                for( final ChannelSftp.LsEntry entry : entries) {
//                        System.out.println(entry.getFilename());
                    try {
                        final ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        sftp.get(ftpAccount + File.separator + XXX_DIR + File.separator +
                                 entry.getFilename(), baos);
                        vaFiles.put(entry.getFilename(), baos.toByteArray());
                        logger.info("File " + ftpAccount + File.separator + XXX_DIR + File.separator + entry.getFilename() + " downloaded.");
                        baos.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    } catch (SftpException e) {
                        e.printStackTrace();
                    }
                }//end for
            } catch (SftpException e) {
                e.printStackTrace();
            }
            break;
        }
    } catch (JSchException e) {
        e.printStackTrace();
    }

    return vaFiles;
}

1 个答案:

答案 0 :(得分:1)

selector很可能无法回复ChannelSftp

无论如何你也不需要那样。

为什么不以处理子文件夹的方式处理文件?

final Vector<ChannelSftp.LsEntry> files = sftp.ls(ftpAccount + File.separator + "*");
final List<ChannelSftp.LsEntry> ftpFileList = files.stream().collect(Collectors.toList());
for (final ChannelSftp.LsEntry lsEntry : ftpFileList) {
   ...
}