/**
 * Copyright 2008-2009. Chongqing Communications Industry Services Co.,Ltd Information Technology Branch. All rights reserved. <a>http://www.crunii.com</a>
 */
package com.crunii.micro.common.utils;

import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;

import org.apache.commons.io.IOUtils;
import org.springframework.util.FileCopyUtils;
import org.springframework.util.StringUtils;

import com.crunii.micro.common.dto.SSHHost;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;

import lombok.extern.slf4j.Slf4j;

/**
 * <pre>
 * sftp调用不频繁的文件上传下载可以采用这个方式，
  *  如果频繁调用请使用连接池方法配置SftpTool，保持连接，提升效率
 * </pre>
 * 
 * @author 田平 create 2019年3月27日下午3:14:58
 */
@Slf4j
public class SftpUtil {

	private static JSch jsch = new JSch();

	public static void main(String[] args) throws Exception {
		String host = "136.6.177.26";
		int port = 22;
		String username = "cqpf";
		String password = "cqpf";
		String localFilePath = "C:\\Users\\Administrator\\Desktop\\json.txt";
		String remotePath = "/cqpf/tianping/a/b";
		SSHHost sshHost = new SSHHost();
		sshHost.setHost(host);
		sshHost.setPort(port);
		sshHost.setUsername(username);
		sshHost.setPassword(password);
		uploadFileSftp(sshHost, remotePath, "中国.txt", FileUtil.getFileInputStream(localFilePath));
		downloadFileSftp(sshHost, remotePath, "中国.txt", "d:\\", "b.txt");
		byte[] bytes = getFileBytesSftp(sshHost, remotePath, "中国.txt");
		System.out.println(new String(bytes, "utf-8"));
	}

	/**
	 * <pre>sftp调用不频繁,注意关闭channel
	  *    使用前请先调用channelSftp.connect();
	 * </pre>
	 * 
	 * @param host
	 * @param username
	 * @param password
	 * @return
	 */
	public static ChannelSftp getChannelSftp(SSHHost sshHost) {
		Session session = null;
		ChannelSftp channelSftp = null;
		try {
			session = jsch.getSession(sshHost.getUsername(), sshHost.getHost(), sshHost.getPort());// 根据用户名，主机ip和端口获取一个Session对象
			session.setPassword(sshHost.getPassword()); // 设置密码
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);// 为Session对象设置properties
			session.setTimeout(sshHost.getSoTimeout());// 设置超时
			session.connect(sshHost.getConnectTimeout());// 通过Session建立连接
			channelSftp = (ChannelSftp) session.openChannel("sftp");
		} catch (Exception e) {
			throw new RuntimeException("getChannelSftp error!", e);
		}
		return channelSftp;
	}

	/**
	 * @param channelSftp
	 * @param remotePath 不允许根目录/
	 */
	public static void mkdirWithP(ChannelSftp channelSftp, String remotePath) {
		if (StringUtils.hasText(remotePath) && remotePath.startsWith("/")) {
			String mkPath = "";
			String[] paths = remotePath.split("/");
			for (int i = 1; i < paths.length; i++) {
				mkPath = mkPath + "/" + paths[i];
				try {
					channelSftp.mkdir(mkPath);
				} catch (Exception ee) {
				}
			}
		}
	}

	/**
	 * <pre>sftp调用不频繁,上传字节流
	 * 如果远程目录不存在会自动创建远程目录
	 * </pre>
	 * 
	 * @param sshHost
	 * @param remotePath
	 * @param remoteName
	 * @param in
	 */
	public static void uploadFileSftp(SSHHost sshHost, String remotePath, String remoteName, InputStream in) {
		ChannelSftp channelSftp = getChannelSftp(sshHost);
		try {
			channelSftp.connect(sshHost.getConnectTimeout());
			mkdirWithP(channelSftp, remotePath);
			channelSftp.put(in, remotePath + "/" + remoteName);
		} catch (Exception e) {
			throw new RuntimeException("uploadFileSftp error!", e);
		} finally {
			IOUtils.closeQuietly(in);
			closeChannelSftp(channelSftp);
		}
	}

	/**
	 * <pre>
	 * sftp调用不频繁,上传文件
	 * 远程目录不存在会自动创建目录
	 * 
	 * </pre>
	 * 
	 * @param sshHost
	 * @param remotePath
	 * @param remoteName
	 * @param localFilePath
	 */
	public static void uploadFileSftp(SSHHost sshHost, String remotePath, String remoteName, String localFilePath) {
		uploadFileSftp(sshHost, remotePath, remoteName, FileUtil.getFileInputStream(localFilePath));
	}

	/**
	 * sftp调用不频繁,获取文件字节数组
	 * 
	 * @param sshHost
	 * @param remotePath
	 * @param remoteName
	 * @return
	 */
	public static byte[] getFileBytesSftp(SSHHost sshHost, String remotePath, String remoteName) {
		ChannelSftp channelSftp = getChannelSftp(sshHost);
		byte[] bytes = null;
		try {
			channelSftp.connect(sshHost.getConnectTimeout());
			InputStream input = channelSftp.get(remotePath + "/" + remoteName);
			bytes = FileCopyUtils.copyToByteArray(input);
		} catch (Exception e) {
			throw new RuntimeException("getFileBytesSftp error!", e);
		} finally {
			closeChannelSftp(channelSftp);
		}
		return bytes;
	}

	/**
	 * sftp调用不频繁,下载文件
	 * 
	 * @param sshHost
	 * @param remotePath
	 * @param remoteName
	 * @param localFilePath
	 * @param localFileName
	 */
	public static void downloadFileSftp(SSHHost sshHost, String remotePath, String remoteName, String localFilePath, String localFileName) {

		ChannelSftp channelSftp = getChannelSftp(sshHost);
		InputStream input = null;
		OutputStream output = null;
		try {
			channelSftp.connect(sshHost.getConnectTimeout());
			input = channelSftp.get(remotePath + "/" + remoteName);
			File file = new File(localFilePath + "/" + localFileName);
			output = new FileOutputStream(file);
			FileCopyUtils.copy(input, output);
		} catch (Exception e) {
			throw new RuntimeException("downloadFileSftp error!", e);
		} finally {
			closeChannelSftp(channelSftp);
		}
	}

	private static void closeChannelSftp(ChannelSftp channelSftp) {
		if (channelSftp != null) {
			try {
				channelSftp.disconnect();
				channelSftp.getSession().disconnect();
			} catch (JSchException e) {
				log.warn("closeChannelSftp error!", e);
			}
		}
	}

}
