使用 JSch 将文件从网络复制到本地路径时文件大小为零

File size is zero while copying them from Network to local path using JSch

我正在尝试编写一项服务,将多个文件从一个网络位置复制到本地项目文件,而我 运行 我的代码低于观察结果

  1. 如果只有一个文件,如果通过网络复制时说它有 520kb,我们就有 519kb。
  2. 如果有多个文件,文件被复制到本地项目路径,但所有文件都是 0kb,只有来自网络的最后一个文件有数据剩余是 0kb。
  3. 文件最初为 0kb,但有时会显示实际大小。

我无法理解这里的问题下面是我的代码

@Override
@SneakyThrows
public boolean createCopyOnNetwork()throws Exception {
    boolean isAbleToCopy =false;
     List<ChannelSftp.LsEntry> files = findFile(getChannelUsingSftp(), filemask);
     byte[] buffer = new byte[1024];
     for(ChannelSftp.LsEntry entry : files) {
         bis = new BufferedInputStream(getChannelUsingSftp().get(entry.getFilename()));
         newFile = new File("downloadedFiles\"+entry.getFilename());
         os = new FileOutputStream(newFile);
         bos = new BufferedOutputStream(os);
     
     while( (readCount = bis.read(buffer)) > 0) {
         bos.write(buffer, 0, readCount);
         isAbleToCopy=true;
       }
}
    return isAbleToCopy;
}

public List<ChannelSftp.LsEntry> findFile(ChannelSftp sftpChannel, String filemask) throws SftpException, JSchException {
    LOG.info("Getting file List using findFile ");
    List<ChannelSftp.LsEntry> list = getChannelUsingSftp().ls(filemask);
    return list;
}
public ChannelSftp getChannelUsingSftp() throws JSchException, SftpException {
    LOG.info("Getting Sftp");
    channel = getSessionOnNetwork(smbUsername,host,port).openChannel("sftp");
    channel.connect();
    ChannelSftp sftpChannel = (ChannelSftp)channel;
    sftpChannel.cd(smbPath);
    return sftpChannel;
}
public  Session getSessionOnNetwork(String smbUsername,String host,int port) throws JSchException {
    LOG.info("Getting session on Network");
    session= jsch.getSession(smbUsername,host,port);
    session.setConfig("StrictHostKeyChecking", "no");
    session.setPassword(smbPassword);
    session.connect();
    return session;
   }

}

缓冲流和写入器必须始终在每个文件的末尾刷新。在 while 循环中完成写入后,调用流上的 flush() 。另外,如评论中所述,必须将 while 循环移至 for 循环中。

在循环内使用 EACH 之后,您缺少对每个流的 close() 调用。对资源使用 try 将有助于在使用后立即清理所有流,并更改代码结构以利用 InputStreamFiles.

的内置调用
for(ChannelSftp.LsEntry entry : files) {
    Path path = Path.of("downloadedFiles",entry.getFilename());
    try(InputStream is = getChannelUsingSftp().get(entry.getFilename());
        OutputStream os = Files.newOutputStream(path))
    {
        is.transferTo(os);
        isAbleToCopy=true;
    }
}

您可能会发现这里有第二个问题与在循环内使用 getChannelUsingSftp() 有关,因此每次文件检索都会重新连接到 ftp 服务器并且不会重新使用与 findFile 生成文件列表时连接到同一服务器。分配给局部变量应该有助于避免过多的服务器连接:

ChannelSftp ftp = getChannelUsingSftp();