If you want to upload a file to another computer, SCP is an excellent way to go. And if you want to do it from within a Java program, your best bet is to use the JSch library from JCraft. They've implemented the SSH protocol purely in Java, and it works splendidly. I've written a nice little class that encapsulates the action of sending a file.
Using the class is pretty simple. It goes like this:
I developed it in Netbeans, and in order to use JSch, the first step is to download the JAR and add it as a library in your project. (When I first tried it, I downloaded the ZIP instead, and added the source to my project; this works, but it's not necessary to compile this library along with your project unless you plan to edit it. I didn't.)
Most of the code in this class is taken from the ScpTo example included in the ZIP file. I recommend reading it. Something to pay close attention to, however, is the SSH known_hosts file. Their example file doesn't take this into account, so if you just run their code, you get an unknown host exception and it doesn't work. So be sure to include the following:
I like it, and it works. But it definitely needs a few things before I'm satisfied.
Using the class is pretty simple. It goes like this:
FileSender fs = new FileSender("172.16.40.128", "user", "user");The constructor takes a host, a username, and a password. The sendFile() method takes a source filename and a destination filename. It returns true if the upload was successful, false if it failed.
boolean ret = fs.sendFile("/home/sschulte/Desktop/AllPhysics.wmv", "AllPhysics.wmv");
I developed it in Netbeans, and in order to use JSch, the first step is to download the JAR and add it as a library in your project. (When I first tried it, I downloaded the ZIP instead, and added the source to my project; this works, but it's not necessary to compile this library along with your project unless you plan to edit it. I didn't.)
Most of the code in this class is taken from the ScpTo example included in the ZIP file. I recommend reading it. Something to pay close attention to, however, is the SSH known_hosts file. Their example file doesn't take this into account, so if you just run their code, you get an unknown host exception and it doesn't work. So be sure to include the following:
String knownHostsFilename = "/home/sschulte/.ssh/known_hosts";(This is, of course, after you instantiate your JSch object.)
jsch.setKnownHosts(knownHostsFilename);
I like it, and it works. But it definitely needs a few things before I'm satisfied.
- Read the known_hosts filename from a config file, rather than compiling it into the code.
- Have a config file for the host/username/password information, possibly for multiple hosts at once.
- Throw exceptions for various types of failures, rather that simply returning false.
24 comments:
Is this line a typo?
FileSender fs = new FileSender("172.16.40.128", "user", "user");
should it be ..?
FileSender fs = new FileSender("172.16.40.128", "user", "password");
I am looking to use jsch to upload documents to a weblogic server.
Would I need to replace the url with the weblogic url from a properties file?
Would it be possible to also post the sendFile() method?
Thanks
newby
It's not a typo; the server I'm using is an Ubuntu JEOS VM, where the password is "user". You're going to want to put the URL of your server in there, whether you get it from a properties file or not.
This is an older version of the sendFile() method, without the abstractions and error handling I've since put in, but it should still be pretty helpful:
public boolean sendFile(String sourceFilename, String destFilename) {
FileInputStream fis = null;
try {
connect();
String command = "scp -p -t " + destFilename;
Channel channel = _session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
OutputStream out = channel.getOutputStream();
InputStream in = channel.getInputStream();
channel.connect();
if (checkAck(in) != 0) {
return false;
}
//send "C0644 filesize filename" where filename doesn't contain a /
long filesize = (new File(sourceFilename)).length();
command = "C0644 " + filesize + " ";
if (sourceFilename.lastIndexOf('/') > 0) {
command += sourceFilename.substring(sourceFilename.lastIndexOf('/') + 1);
} else {
command += sourceFilename;
}
command += "\n";
out.write(command.getBytes());
out.flush();
if (checkAck(in) != 0) {
return false;
}
//send the contents of the source file
fis = new FileInputStream(sourceFilename);
byte[] buf = new byte[1024];
while (true) {
int len = fis.read(buf, 0, buf.length);
if (len <= 0) {
break;
}
out.write(buf, 0, len);
}
fis.close();
fis = null;
//send '\0' to end it
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
if (checkAck(in) != 0) {
return false;
}
out.close();
channel.disconnect();
_session.disconnect();
return true;
} catch (Exception e) {
e.printStackTrace();
try {
if (fis != null) {
fis.close();
}
} catch (Exception ee) {
ee.printStackTrace();
}
}
return false;
}
Enjoy.
Thanks for posting the code. Is SCP the same or similar to SFTP, which is secure FTP? I have seen jscp used to sftp files over.
Hi Sean,
I am in the process of implementing JSch: SCP a File in Java, but have not had much success. It is most likely because I have not coded the SSH known_hosts correction you mentioned. This is because I did not find a known_hosts file on our server. Do I need to install SSH on the server in order to get a known_hosts file? Please advise.
Thanks, Newby.
I was googling around and happened upon your blog post. I had some spare time and quickly wrote a wrapper class for scp'ing files with jsch. I don't have it packaged into a jar yet, but you are welcome to check it out from my google code repository and build it yourself.
Here's the project page: http://code.google.com/p/securechannelfacade/
I'm using maven so building should be pretty straightforward... `mvn clean install`
I was able to get it to work without setting known hosts by specifying session.setConfig("StrictHostKeyChecking", "no")
So how do I specify which directory to scp to/from if I can't use a '/' character in the C0644 command?
Hey Sean can you share your java code.. I would like to try out your class for using JSch... please let me know where can I download it from.
Hi Seam,
I am in need of a java program which will transfer a file from one pc to another. Where do i start? Sorry to ask...But i couldn't get the right way.
Please guide me...
Rakesh.
mehra.16@gmail.com
I have successfully implemented the Jsch code on the server and able to upload a file from server to another computer, but when i try to upload the file from other computer by giving the server ip address as url in address bar(say http://192.168.1.54:8084/upload), the upload is not successful. It show an FileNotFoundException.
Thanks,
ethan
ethanbroad@rocketmail.com
Hi Sean
I am using the latest jar file jsch-0.1.42.jar from jcraft. I am having a wiered issues ,sometimes the file copied to the remote computer has only zero bytes. I am using the same code what you are using except little diffeence wheer you are calling the checkAck method and am not. Here is my code. My question is
1.) what is the importance of the code
if (checkAck(in) != 0) {
return false;
}
should I include in my send file method.
2.) How can I check the size of the transferred file.
I would highly appreciate,
If you can throw soem light on this .
Thank you
CT
Where can i get this code?
I tried the same. No error occurs but the file isnt uploaded in remote location. Following is my code:
public boolean sendFile(String sourceFilename, String destFilename)
{
FileInputStream fis = null;
Session session = null;
try
{
JSch jsch = new JSch();
//jsch.setKnownHosts("D:/sftpRoot/test");
String knownHostsFilename = "/home/sschulte/.ssh/known_hosts";
jsch.setKnownHosts(knownHostsFilename);
// Create session
session = jsch.getSession(this.user, this.host, 50000);
UserInfo userInfo = new MyUserInfo();
((MyUserInfo)userInfo).setPassword(this.password);
session.setUserInfo(userInfo);
session.setPassword(this.password);
// connect
session.connect();
String command = "scp -p -t " + destFilename;
Channel channel = session.openChannel("exec");
((ChannelExec) channel).setCommand(command);
OutputStream out = channel.getOutputStream();
//InputStream in = channel.getInputStream();
channel.connect();
//send "C0644 filesize filename" where filename doesn't contain a /
long filesize = (new File(sourceFilename)).length();
command = "C0644 " + filesize + " ";
if (sourceFilename.lastIndexOf('/') > 0)
{
command += sourceFilename.substring(sourceFilename.lastIndexOf('/') + 1);
}
else
{
command += sourceFilename;
}
command += "\n";
out.write(command.getBytes());
out.flush();
//send the contents of the source file
fis = new FileInputStream(sourceFilename);
byte[] buf = new byte[1024];
while (true)
{
int len = fis.read(buf, 0, buf.length);
if (len <= 0)
{
break;
}
out.write(buf, 0, len);
}
fis.close();
fis = null;
//send '\0' to end it
buf[0] = 0;
out.write(buf, 0, 1);
out.flush();
out.close();
channel.disconnect();
session.disconnect();
return true;
}
catch (Exception e)
{
e.printStackTrace();
try
{
if (fis != null)
{
fis.close();
}
}
catch (Exception ee)
{
ee.printStackTrace();
}
}
return false;
}
public static class MyUserInfo implements UserInfo
{
public String password = null;
/**
*
* @param password
*/
public void setPassword(String password)
{
this.password = password;
}
public String getPassword()
{
return this.password;
}
public boolean promptYesNo(String str)
{
return true;
}
public String getPassphrase()
{
return null;
}
public boolean promptPassphrase(String message)
{
return true;
}
public void showMessage(String message)
{
}
public boolean promptPassword(String message)
{
return true;
}
}
public static void main(String[] args)
{
FileUploader fileUploader = new FileUploader("192.168.33.82", "test", "test");
boolean uploadStatus = fileUploader.sendFile("D:/test111.txt", "test111.txt");
System.out.println("File Upload successful: "+uploadStatus);
}
Hi
Same question as JKlassMoney had, where can I get this class?
Good effort mate. But you can simply use JSch's built in ChannelSftp class. It does all the heavy lifting for you.
For a full integrated solution with JFileUpload.
http://www.jfileupload.com/products/scp/index.html
Hello Sean, can you share your java class ? I have to automatically upload files via SCP and so I am very interested in your code... please let me know where can I download it from.
how can i get this java class? Very needed
I used the same code but copying failed if I try to copy to a new directory calculated during prog execution which doesnt exist. How to create a new directory and then scp the file from source to it?
I" using an Ant script for SCP.
You can find the tutorial at
http://sshadmincontrol.com/jsch-scp-files-from-multiple-hosts-using-apache-ant-task
Try using the java code from
http://sshadmincontrol.com/sftp-server-communication-in-java-using-jsch
I have tried it with multiple clients at the same time.At some time it is giving some error as
"Exception in thread "Exec thread 223.235.25.115" java.lang.NullPointerException
at com.jcraft.jsch.ChannelSession.run(Unknown Source)
at java.lang.Thread.run(Thread.java:662)
Kindly advice me to solve the issue..
Am not able to see FileSender class in jsch-0.1.50.jar.
Could you please tell any other option to file upload using jsch__.jar
Post a Comment