Transfer folder and subfolders using channelsftp in JSch?

纵饮孤独 提交于 2019-11-26 20:47:13

问题


I want to transfer a folder and a subfolder using 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?


回答1:


To work with multilevel folder structures in jsch you:

  1. enter them;
  2. list their contents;
  3. do smth with every found item;
  4. repeat 1, 2 & 3 if subfolder is found.

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())) { // 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).



回答2:


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);

                    }

                }
            }

         }



回答3:


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());
	}

}


来源:https://stackoverflow.com/questions/11650013/transfer-folder-and-subfolders-using-channelsftp-in-jsch

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!