【问题标题】:Transfer folder and subfolders using ChannelSftp in JSch?在 JSch 中使用 ChannelSftp 传输文件夹和子文件夹?
【发布时间】:2012-07-25 12:44:02
【问题描述】:

我想使用 JSch ChannelSftp 传输一个文件夹和一个子文件夹。我可以使用channelsftp.put(src, dest) 命令成功传输文件,但这不适用于文件夹(至少我无法使其工作)。那么有人可以解释一下如何使用ChannelSftp 传输文件夹和子文件夹吗?

【问题讨论】:

    标签: java sftp jsch


    【解决方案1】:

    要在 jsch 中使用多级文件夹结构,您:

    1. 输入它们;
    2. 列出它们的内容;
    3. 对每一个找到的物品进行处理;
    4. 如果找到子文件夹,请重复 1、2 和 3。

    在 JSCH 类中下载 dirs 方法:

    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.
            }
        }
    }
    

    删除 JSCH 类中的 dirs 方法:

    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.");
    }
    

    从外部调用这些方法,例如:

    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】:

      根据我的理解,上面的代码(按 zon)可以下载。我需要上传到远程服务器。我写了下面的代码来实现同样的目的。如果有任何问题,请尝试并发表评论(它会忽略以“. ")

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

      【讨论】:

      • JSCH 用于远程连接。要使用本地文件系统,您将使用 java.io.File 类。但是你也可以尝试连接你的本地主机,就好像它是一个远程的一样。
      • Zon.. 我发布的这段代码是上传到远程系统...(此代码用于将 ear 文件从开发人员箱上传到服务器箱 - 自动使用 jenkins.. )
      • 这是优秀的代码并且工作正常。但是如果我也想复制以点(。)开头的文件怎么办。在评论那行之后,它仍然没有复制相同的内容吗?
      • 是的,它应该.. 尝试注释掉这一行:if(!localFile.getName().startsWith("."))
      【解决方案3】:

      发件人: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());
      	}
      
      }

      【讨论】:

        猜你喜欢
        • 2018-06-14
        • 2021-12-24
        • 1970-01-01
        • 1970-01-01
        • 2012-05-10
        • 2013-06-05
        • 2021-07-02
        • 2016-03-10
        相关资源
        最近更新 更多