使用 JSch 将文件从网络复制到本地路径时文件大小为零
File size is zero while copying them from Network to local path using JSch
我正在尝试编写一项服务,将多个文件从一个网络位置复制到本地项目文件,而我 运行 我的代码低于观察结果
- 如果只有一个文件,如果通过网络复制时说它有 520kb,我们就有 519kb。
- 如果有多个文件,文件被复制到本地项目路径,但所有文件都是 0kb,只有来自网络的最后一个文件有数据剩余是 0kb。
- 文件最初为 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 将有助于在使用后立即清理所有流,并更改代码结构以利用 InputStream
和 Files
.
的内置调用
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();
我正在尝试编写一项服务,将多个文件从一个网络位置复制到本地项目文件,而我 运行 我的代码低于观察结果
- 如果只有一个文件,如果通过网络复制时说它有 520kb,我们就有 519kb。
- 如果有多个文件,文件被复制到本地项目路径,但所有文件都是 0kb,只有来自网络的最后一个文件有数据剩余是 0kb。
- 文件最初为 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 将有助于在使用后立即清理所有流,并更改代码结构以利用 InputStream
和 Files
.
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();