提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档


文章目录

  • 前言
  • 一、JSch下载及使用方法
  • 1. jar包下载
  • 2. 添加maven依赖
  • 二、代码样例(传输单个文件或文件夹至服务器指定目录下)



前言

JSch是SSH2的一个纯Java实现。JSch允许你连接到一个sshd服务器,用来端口转发,X11转发,文件传输等等。可以将它的功能集成到自己的Java程序中。JSch也有对应支持J2ME的版本, 但不在本文范围内, 感兴趣的可以自行研究


一、JSch下载及使用方法

1. jar包下载

官网地址 http://www.jcraft.com/jsch/下载链接在该页面中部

2. 添加maven依赖

<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
	<groupId>com.jcraft</groupId>
	<artifactId>jsch</artifactId>
	<version>0.1.55</version>
</dependency>

二、代码样例(传输单个文件或文件夹至服务器指定目录下)

里面的注释很详细, 不再多做说明:

import java.io.File;
import java.util.List;
import java.util.Properties;
import java.util.Vector;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.ChannelSftp.LsEntry;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpException;

/**
 * 
 * @author yuguagua
 * @email feimeideyanggao@126.com
 * @date 2021年2月5日 下午3:50:28
 * @company 哈尔滨亿时代数码科技开发有限公司
 */
public class SFTPChannelUtils {

	Session session = null;
	Channel channel = null;

	// 获取sftp channel对象
	public ChannelSftp getChannelSftp() throws JSchException {
		// ssh服务器的IP、用户名、密码和端口
		String sftpHost = "192.168.1.241", sftpUsername = "username", sftpPassword = "password";
		int sftpPort = 22;

		JSch jsch = new JSch(); // 创建JSch对象
		System.out.println(" 创建JSch对象");
		session = jsch.getSession(sftpUsername, sftpHost, sftpPort);// 获取sesson对象
		System.out.println("获取sesson对象");
		session.setPassword(sftpPassword);// 设置sftp访问密码

		Properties config = new Properties();
		config.put("StrictHostKeyChecking", "no");
		session.setConfig(config);// 为session重新设置参数
		session.setTimeout(30000);// 设置超时
		System.out.println("相关连接参数设置完毕, 准备建立连接");
		session.connect();// 建立连接
		System.out.println("建立连接");

		channel = session.openChannel("sftp"); // 打开sftp通道
		System.out.println("打开sftp通道");
		channel.connect();// 建立sftp通道连接
		System.out.println("建立sftp通道连接");
		return (ChannelSftp) channel;
	}

	public void closeChannel() {
		if (channel != null) {
			channel.disconnect();
			System.out.println("断开channel");
		}
		if (session != null) {
			session.disconnect();
			System.out.println("断开session");
		}
	}
	
	public static void main(String[] args) {

		try {
			// JSch支持三种文件传输模式:
			// OVERWRITE 完全覆盖模式,这是JSch的 默认
			// 文件传输模式,即如果目标文件已经存在,传输的文件将完全覆盖目标文件,产生新的文件。
			// RESUME 恢复模式,如果文件已经传输一部分,这时由于网络或其他任何原因导致文件传输中断,如果下一次传输相同的文件,
			// 则会从上一次中断的地方续传。
			// APPEND 追加模式,如果目标文件已存在,传输的文件将在目标文件后追加。
			SFTPChannelUtils sftpChannel = new SFTPChannelUtils();
			ChannelSftp channel = sftpChannel.getChannelSftp();
			/**	3种传输单个文件的方法	begin**/
			String srcFile = "d:\\testfile.rar", destFile = "/home/cbj/yuguagua/tmp/testfile.rar";
			// String srcFile = "d:\\jquery-ui-1.10.4.custom.js", destFile =
			// "/var/www/html/jquery-ui-1.10.4.custom.js";
			System.out.println("准备传输文件");
			// 以下使用3种put方法来传输文件
//			// 方法 1/3
//			OutputStream out = channel.put(destFile, ChannelSftp.OVERWRITE);
//			// 默认使用OVERWRITE模式
//			byte[] buff = new byte[1024 * 256]; // 设定每次传输的数据块大小为256KB
//			int read;
//			if (out != null) {
//				System.out.println("Start to read input stream");
//				InputStream is = new FileInputStream(srcFile);
//				do {
//					read = is.read(buff, 0, buff.length);
//					if (read > 0) {
//						out.write(buff, 0, read);
//					}
//					out.flush();
//				} while (read >= 0);
//			}

			// 方法 2/3
			// channel.put(srcFile, destFile, ChannelSftp.APPEND);

			// 方法 3/3 
			// channel.put(new FileInputStream(srcFile), destFile,
			// ChannelSftp.OVERWRITE);
			
			/**	3种传输单个文件的方法	end **/
			
			
			/** 传输文件夹到指服务器指定目录下	begin	**/
			String srcDirectory = "d:\\Program Files\\", destDirectory = "/home/cbj/yuguagua/tmp/test";
			sftpChannel.chuanshu(channel, srcDirectory, destDirectory);
			/** 传输文件夹到指服务器指定目录下	end	**/
			
			System.out.println("传输完成");
			channel.quit();
			sftpChannel.closeChannel();

		} catch (Exception e) {
			e.printStackTrace();
			// } catch (FileNotFoundException e) {
			// e.printStackTrace();
			// } catch (IOException e) {
			// e.printStackTrace();
		}

	}

	/**
	 * 向服务器指定目录下以覆盖模式传输文件|文件夹
	 * 
	 * @author yuguagua
	 * @email feimeideyanggao@126.com
	 * @create 2021年2月6日
	 * @param channel
	 *            sftp通道对象
	 * @param 源文件[目录]路径,
	 *            可为文件或文件目录
	 * @destFilePath 目标文件夹目录, 必须存在在且必须为目录!!!不可以是文件!!!, 后缀不要加 / , 传输的文件夹会新建在此目录下
	 * @return
	 */
	public void chuanshu(ChannelSftp channel, String srcFilePath, String destFilePath) {
		File file = new File(srcFilePath);
		String subDestFilePath = destFilePath + "/" + file.getName(); // 真·文件目录
		// 1. 源文件为目录, 则列表显示其下所有的文件夹、文件
		if (file.isDirectory()) {
			// 1.1 在destFilePath目录下检查本目录是否存在, 存在则删除再创建; 不存在则新创建
			try {
				channel.cd(subDestFilePath);
				System.out.println("目标服务器上 目录: " + subDestFilePath + " 存在, 先予以删除");
				channel.cd(destFilePath);
				deleteTargetFile(channel, subDestFilePath);
				System.out.println("目标服务器上 目录: " + subDestFilePath + " 删除成功");
				channel.mkdir(subDestFilePath);
				System.out.println("目标服务器上 目录: " + subDestFilePath + " 删除后创建成功");
			} catch (SftpException e) {
				System.out.println("目标服务器上 目录: " + subDestFilePath + " 不存在, 正在创建");
				try {
					channel.mkdir(subDestFilePath);
				} catch (SftpException e1) {
					System.out.println("目标服务器上 创建目录: " + subDestFilePath + " 出错." + e1.getLocalizedMessage());
				}
			}
			File subfiles[] = file.listFiles();
			for (int i = 0; i < subfiles.length; i++) {
				chuanshu(channel, subfiles[i].getAbsolutePath(), subDestFilePath);
			}
		} else {
			// 2. 源文件为文件,将文件传输到 destFilePath目录下
			// // 2.1 检查destFilePath目录是否存在, 不存在则创建
			// try {
			// channel.cd(destFilePath);
			// } catch (SftpException e) {
			// System.out.println("目录: " + destFilePath + " 不存在, 正在创建");
			// try {
			// channel.mkdir(destFilePath);
			// } catch (SftpException e1) {
			// System.out.println("创建目录: " + destFilePath + " 出错." +
			// e1.getLocalizedMessage());
			//
			// }
			// }
			try {
				channel.cd(destFilePath);
				channel.put(srcFilePath, destFilePath + "/" + file.getName(), ChannelSftp.OVERWRITE);
				System.out.println("传输文件: " + srcFilePath + "  到  " + destFilePath + "/" + file.getName() + "  成功.");
			} catch (SftpException e) {
				System.out.println("传输文件: " + srcFilePath + "  到  " + destFilePath + "/" + file.getName() + "  出错."
						+ e.getLocalizedMessage());
			}
		}

	}

	/**
	 * 删除服务器指定的文件夹及其里面的所有内容
	 * 
	 * @author yuguagua
	 * @email feimeideyanggao@126.com
	 * @create 2021年2月6日
	 * @param targetFilePath
	 *            要删除的文件或文件夹路径, 应为绝对路径, 且非空
	 * @return
	 */
	public void deleteTargetFile(ChannelSftp channel, String targetFilePath) {
		try {
			// 1. 路径为文件夹
			if (channel.stat(targetFilePath).isDir()) {
				channel.cd(targetFilePath);
				Vector<LsEntry> entries = channel.ls(".");
				for (LsEntry subFilePath : entries) {
					String fileName = subFilePath.getFilename();
					if (".".equals(fileName) || "..".equals(fileName)) {
						continue;
					}
					deleteTargetFile(channel, subFilePath.getFilename());
				}
				channel.cd("..");
				channel.rmdir(targetFilePath);
				System.out.println("删除文件夹: " + targetFilePath + " 成功. ");
			} else {
				// 2. 路径为文件
				try {
					channel.rm(targetFilePath);
					System.out.println("删除文件: " + targetFilePath + " 成功. ");
				} catch (SftpException e) {
					System.out.println("删除文件: " + targetFilePath + " 出错. " + e.getMessage());
				}
			}
		} catch (SftpException e) {
			System.out.println("判断文件: " + targetFilePath + " 类型出错. " + e.getMessage());
		}

	}
}