Reputation: 1125
I want to transfer a folder and a subfolder using JSch ChannelSftp
. I can successfully transfer files using channelsftp.put(src, dest)
command but this does not work for folders (at least I could not make it work). So can someone please explain how can I transfer folders and subfolders using ChannelSftp
?
Upvotes: 6
Views: 30115
Reputation: 19880
To work with multilevel folder structures in jsch you:
DOWNLOAD dirs method inside your JSCH class:
public void downloadDir(String sourcePath, String destPath) throws SftpException { // With subfolders and all files.
// Create local folders if absent.
try {
new File(destPath).mkdirs();
} catch (Exception e) {
System.out.println("Error at : " + destPath);
}
sftpChannel.lcd(destPath);
// Copy remote folders one by one.
lsFolderCopy(sourcePath, destPath); // Separated because loops itself inside for subfolders.
}
private void lsFolderCopy(String sourcePath, String destPath) throws SftpException { // List source (remote, sftp) directory and create a local copy of it - method for every single directory.
Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(sourcePath); // List source directory structure.
for (ChannelSftp.LsEntry oListItem : list) { // Iterate objects in the list to get file/folder names.
if (!oListItem.getAttrs().isDir()) { // If it is a file (not a directory).
if (!(new File(destPath + "/" + oListItem.getFilename())).exists() || (oListItem.getAttrs().getMTime() > Long.valueOf(new File(destPath + "/" + oListItem.getFilename()).lastModified() / (long) 1000).intValue())) { // Download only if changed later.
new File(destPath + "/" + oListItem.getFilename());
sftpChannel.get(sourcePath + "/" + oListItem.getFilename(), destPath + "/" + oListItem.getFilename()); // Grab file from source ([source filename], [destination filename]).
}
} else if (!(".".equals(oListItem.getFilename()) || "..".equals(oListItem.getFilename()))) {
new File(destPath + "/" + oListItem.getFilename()).mkdirs(); // Empty folder copy.
lsFolderCopy(sourcePath + "/" + oListItem.getFilename(), destPath + "/" + oListItem.getFilename()); // Enter found folder on server to read its contents and create locally.
}
}
}
REMOVE dirs method inside your JSCH class:
try {
sftpChannel.cd(dir);
Vector<ChannelSftp.LsEntry> list = sftpChannel.ls(dir); // List source directory structure.
for (ChannelSftp.LsEntry oListItem : list) { // Iterate objects in the list to get file/folder names.
if (!oListItem.getAttrs().isDir()) { // If it is a file (not a directory).
sftpChannel.rm(dir + "/" + oListItem.getFilename()); // Remove file.
} else if (!(".".equals(oListItem.getFilename()) || "..".equals(oListItem.getFilename()))) { // If it is a subdir.
try {
sftpChannel.rmdir(dir + "/" + oListItem.getFilename()); // Try removing subdir.
} catch (Exception e) { // If subdir is not empty and error occurs.
lsFolderRemove(dir + "/" + oListItem.getFilename()); // Do lsFolderRemove on this subdir to enter it and clear its contents.
}
}
}
sftpChannel.rmdir(dir); // Finally remove the required dir.
} catch (SftpException sftpException) {
System.out.println("Removing " + dir + " failed. It may be already deleted.");
}
CALL these methods from outside like:
MyJSCHClass sftp = new MyJSCHClass();
sftp.removeDir("/mypublic/myfolders");
sftp.disconnect(); // Disconnecting is obligatory - otherwise changes on server can be discarded (e.g. loaded folder disappears).
Upvotes: 14
Reputation: 11
From: http://the-project.net16.net/Projekte/projekte/Projekte/Programmieren/sftp-synchronisierung.html
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.util.Vector;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.SftpException;
public class FileMaster {
public boolean FileAction;
public File local;
public String serverDir;
public ChannelSftp channel;
public FileMaster(boolean copyOrDelete, File local, String to, ChannelSftp channel){
this.FileAction = copyOrDelete;
this.local = local;
this.serverDir = to;
this.channel = channel;
}
/*
* If FileAction = true, the File local is copied to the serverDir, else the file is deleted.
*/
public void runMaster() throws FileNotFoundException, SftpException{
if(FileAction){
copy(local, serverDir, channel);
} else {
delete(serverDir, channel);
}
}
/*
* Copies recursive
*/
public static void copy(File localFile, String destPath, ChannelSftp clientChannel) throws SftpException, FileNotFoundException{
if(localFile.isDirectory()){
clientChannel.mkdir(localFile.getName());
GUI.addToConsole("Created Folder: " + localFile.getName() + " in " + destPath);
destPath = destPath + "/" + localFile.getName();
clientChannel.cd(destPath);
for(File file: localFile.listFiles()){
copy(file, destPath, clientChannel);
}
clientChannel.cd(destPath.substring(0, destPath.lastIndexOf('/')));
} else {
GUI.addToConsole("Copying File: " + localFile.getName() + " to " + destPath);
clientChannel.put(new FileInputStream(localFile), localFile.getName(),ChannelSftp.OVERWRITE);
}
}
/*
* File/Folder is deleted, but not recursive
*/
public void delete(String filename, ChannelSftp sFTPchannel) throws SftpException{
if(sFTPchannel.stat(filename).isDir()){
@SuppressWarnings("unchecked")
Vector<LsEntry> fileList = sFTPchannel.ls(filename);
sFTPchannel.cd(filename);
int size = fileList.size();
for(int i = 0; i < size; i++){
if(!fileList.get(i).getFilename().startsWith(".")){
delete(fileList.get(i).getFilename(), sFTPchannel);
}
}
sFTPchannel.cd("..");
sFTPchannel.rmdir(filename);
} else {
sFTPchannel.rm(filename.toString());
}
GUI.addToConsole("Deleted: " + filename + " in " + sFTPchannel.pwd());
}
}
Upvotes: 0
Reputation: 319
Above code(by zon) works for download as per my understanding.I need to upload to a remote server.I wrote below code to achieve the same.Please try and comment if any issue(it ignores files starting with ".")
private static void lsFolderCopy(String sourcePath, String destPath,
ChannelSftp sftpChannel) throws SftpException, FileNotFoundException {
File localFile = new File(sourcePath);
if(localFile.isFile())
{
//copy if it is a file
sftpChannel.cd(destPath);
if(!localFile.getName().startsWith("."))
sftpChannel.put(new FileInputStream(localFile), localFile.getName(),ChannelSftp.OVERWRITE);
}
else{
System.out.println("inside else "+localFile.getName());
File[] files = localFile.listFiles();
if(files!=null && files.length > 0 && !localFile.getName().startsWith("."))
{
sftpChannel.cd(destPath);
SftpATTRS attrs = null;
//check if the directory is already existing
try {
attrs = sftpChannel.stat(destPath+"/"+localFile.getName());
} catch (Exception e) {
System.out.println(destPath+"/"+localFile.getName()+" not found");
}
//else create a directory
if (attrs != null) {
System.out.println("Directory exists IsDir="+attrs.isDir());
} else {
System.out.println("Creating dir "+localFile.getName());
sftpChannel.mkdir(localFile.getName());
}
//System.out.println("length " + files.length);
for(int i =0;i<files.length;i++)
{
lsFolderCopy(files[i].getAbsolutePath(),destPath+"/"+localFile.getName(),sftpChannel);
}
}
}
}
Upvotes: 5