如何使用 Java SFTP 库 JSch 将文件从一个目录传输到另一个目录?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32787456/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I transfer a file from one directory to another using Java SFTP Library JSch?
提问by Coffee
I need to program a file transfer using JSch library. I have a simple directory with two folders -
我需要使用 JSch 库对文件传输进行编程。我有一个包含两个文件夹的简单目录 -
In the SFTP_1
folder, I have a bitmap image. And the SFTP_2
folder is just an empty folder. My goal is to transfer the image using SFTP from SFTP_1 to SFTP_2 .
在SFTP_1
文件夹中,我有一个位图图像。而SFTP_2
文件夹只是一个空文件夹。我的目标是使用 SFTP 将图像从 SFTP_1 传输到 SFTP_2 。
Here is my code thus far :
到目前为止,这是我的代码:
import com.jcraft.jsch.*;
import java.awt.Desktop;
import java.nio.channels.Channel;
public class FileTransfer {
public FileTransfer() {
super();
}
public static void main (String[] args) {
FileTransfer fileTransfer = new FileTransfer();
JSch jsch = new JSch();
try {
String host = "127.0.0.1";
int port = 22;
String user = "user";
Session session = jsch.getSession(user, host, port);
session = jsch.getSession("username", "127.0.0.1", 22);
session.connect();
//Channel channel = session.openChannel("sftp");
ChannelSftp sftp = null;
sftp = (ChannelSftp)session.openChannel("sftp") ; //channel;
//channel.connect();
//Channel channel = session.openChannel("shell");
sftp.rename("C:\Users\ADMIN\Desktop\Work\ConnectOne_Bancorp\Java_Work\SFTP_1\house.bmp", "C:\Users\ADMIN\Desktop\Work\ConnectOne_Bancorp\Java_Work\SFTP_2\house.bmp"); // /SFTP_1/file.txt
//sftpChannel.get("remotefile.txt", "localfile.txt");
//sftpChannel.exit();
session.disconnect();
} catch (JSchException e) {
e.printStackTrace();
} catch (SftpException e) {
e.printStackTrace();
}
}
}
What I would like to do is to simply transfer a file from one directory in my machine, to another directory. any tips appreciated, thanks !
我想要做的是简单地将文件从我机器中的一个目录传输到另一个目录。任何提示表示赞赏,谢谢!
采纳答案by Edwin Buck
Note that to copy between two folders, one doesn't need to use SFTP. One can copy from one folder to another without involving the SFTP protocol which is primarly used to copy files remotely, either from the local machine to a remote machine, or from a remote machine to (the same or a different) remote machine, or from the remote machine to the local machine.
请注意,要在两个文件夹之间进行复制,不需要使用 SFTP。可以从一个文件夹复制到另一个文件夹而不涉及 SFTP 协议,该协议主要用于远程复制文件,从本地机器到远程机器,或从远程机器到(相同或不同的)远程机器,或从远程机器到本地机器。
That's because the FTP is a network based protocol. So using it (or any of it's related protocols) is going to use the network (or a simulated network).
那是因为 FTP 是基于网络的协议。因此,使用它(或其任何相关协议)将使用网络(或模拟网络)。
The security that JSch provides is security designed to protect from certain kinds of attacks that occur on networks. It will not provide any extra security within the machine.
JSch 提供的安全性旨在防止网络上发生的某些类型的攻击。它不会在机器内提供任何额外的安全性。
To copy files between folders on a single machine, the simplest way to do so is not to use JSch, like so
在单机上的文件夹之间复制文件,最简单的方法就是不要使用JSch,像这样
private static void copyFileUsingJava7Files(File source, File dest)
throws IOException {
Files.copy(source.toPath(), dest.toPath());
}
There are other techniques, and if you really want to use JSch, you need to realize that JSch must be provided a lot of "extra" information to connect to the machine you are on, because it will try to connect to this machine as if it were connecting from across the network
还有其他技术,如果你真的想使用 JSch,你需要意识到 JSch 必须提供很多“额外”的信息才能连接到你所在的机器,因为它会尝试连接到这台机器,好像它是通过网络连接的
Session sessionRead = jsch.getSession("username", "127.0.0.1", 22);
sessionRead.connect();
Session sessionWrite = jsch.getSession("username", "127.0.0.1", 22);
sessionWrite.connect();
ChannelSftp channelRead = (ChannelSftp)sessionRead.openChannel("sftp");
channelRead.connect();
ChannelSftp channelWrite = (ChannelSftp)sessionWrite.openChannel("sftp");
channelWrite.connect();
PipedInputStream pin = new PipedInputStream(2048);
PipedOutputStream pout = new PipedOutputStream(pin);
channelRead.get("/path/to/your/file/including/filename.txt", pout);
channelWrite.put(pin, "/path/to/your/file/destination/including/filename.txt");
channelRead.disconnect();
channelWrite.disconnect();
sessionRead.disconnect();
sessionWrite.disconnect();
The above code lacks error checking, exception handling, and fall back routines for if files are missing, networks are not up, etc. But you should get the main idea.
上面的代码缺少错误检查、异常处理以及文件丢失、网络未启动等的回退例程。但您应该了解主要思想。
It should also be obvious that using a network protocol where no network protocol needs to exist opens the door to a lot more failure scenarios. Only use the SFTP method if your program is soon meant to copy files that are not both located on your machine.
很明显,使用不需要网络协议的网络协议为更多的故障场景打开了大门。如果您的程序很快要复制不在您的机器上的文件,则仅使用 SFTP 方法。
回答by sibnick
Actually JSch is designed for remote work, and file system modification is one of the type such work. @Edwin Buck answer uses network for coping between local folders on remote host. There is better approach:
实际上 JSch 是为远程工作而设计的,文件系统修改是此类工作的一种。@Edwin Buck 回答使用网络在远程主机上的本地文件夹之间进行处理。有更好的方法:
session.connect();
ChannelExec exec = (ChannelExec) session.openChannel("exec");
exec.setCommand("cp a.out b.out");
exec.connect();
I have no windows on the hand, as result my sample is for unix. But the idea is simple: execute copy command on the remote host.
我手头没有窗户,因此我的样本适用于 unix。但想法很简单:在远程主机上执行复制命令。
回答by Matt Campbell
If the original poster is actually looking for a working example of JSch in action between two distinct FTP sites, here goes:
如果原始发布者实际上是在寻找在两个不同 FTP 站点之间运行的 JSch 工作示例,请访问:
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
...
JSch jsch = new JSch();
JSch session = null;
try {
session = jsch.getSession(userid, sourceservername, sourceserverport);
session.setPassword(sourceserverpassword);
Properties props = new Properties();
props.put("StrictHostKeyChecking", "no");
session.setConfig(props);
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChanelSftp channelsftp = (ChannelSftp) channel;
channelsftp.cd(sourcefilepath);
channelsftp.lcd(localfilepath);
FileOutputStream fos = new FileOutputStream(new File(localfilepath + "/" + localfilename));
channelsftp.get(sourcefilename, fos);
fos.flush();
fos.close();
channelsftp.disconnect()
session.disconnect();
} catch (Exception e) {
e.printStackTrace();
}
In practice you might break up these actions into separate try{}catch(){} blocked statements so as to introduce more granular error reporting, as well as add any informational output lines to inform the user of status, etc. But this'll get you there. Admittedly while the JSch examples are better than most such examples from freeware libraries, even good ones like this one, there can be some omissions among them around details that can make or break your attempt to get the things to work. Hope this helps if not the original poster, then someone else looking for a working JSch example. Once you have it working, it does go like a charm, so it's worth the trouble.
在实践中,您可以将这些操作分解为单独的 try{}catch(){} 阻塞语句,以便引入更精细的错误报告,并添加任何信息输出行以通知用户状态等。但这会带你到那里。诚然,虽然 JSch 示例比免费软件库中的大多数此类示例要好,即使是像这样的好示例,但其中可能存在一些遗漏细节,这些细节可能会影响您使事情正常工作的尝试。希望这有助于如果不是原始海报,那么其他人正在寻找一个有效的 JSch 示例。一旦你让它工作,它就像一个魅力,所以值得麻烦。
回答by Martin Prikryl
A core SFTP protocol does not support duplicating remote files.
核心 SFTP 协议不支持复制远程文件。
There's a draft of copy-file
extension to the protocol, but that's supported by only few SFTP servers (ProFTPD/mod_sftpand Bitvise SFTP server for example).
copy-file
该协议有一个扩展草案,但只有少数 SFTP 服务器支持(例如ProFTPD/mod_sftp和 Bitvise SFTP 服务器)。
It's definitely not supported by the most widespread OpenSSH SFTP server.
最广泛使用的 OpenSSH SFTP 服务器绝对不支持它。
And it's also not supported by the JSch library.
而且 JSch 库也不支持它。
See also my answer to How can I copy/duplicate a file to another directory using SFTP?
另请参阅我对如何使用 SFTP 将文件复制/复制到另一个目录的回答?
So actually using the cp
shell command over an "exec" channel (ChannelExec
) is unfortunately the best available approach (assuming you connect to a *nix server and you have a shell access).
因此,不幸的是,实际上cp
在“exec”通道 ( ChannelExec
) 上使用shell 命令是最好的可用方法(假设您连接到 *nix 服务器并且您具有 shell 访问权限)。
If you do not have a shell access, then your only option is indeed to download the file to a local temporary folder and upload it back to the new location (or use streams, to avoid a temporary file). This is what the accepted answer by @Edwin Buck shows.
如果您没有外壳访问权限,那么您唯一的选择确实是将文件下载到本地临时文件夹并将其上传回新位置(或使用流,以避免临时文件)。这是@Edwin Buck 接受的答案所显示的内容。