springcloud jsch sftp微服务

jsch包引入


            com.jcraft
            jsch
        

在启动类加一个bean注入工具类,工具类在下面

将sftp上传的类注入进spring里

	
	@Bean
    public SftpUtil getSftpUtil() {
        return SftpUtil.getSftpUtil();
    }

调用

import java.io.IOException;
import java.text.SimpleDateFormat;
import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

@Component
public class SftpUpload {
    //注入上面的工具
    @Autowired
    SftpUtil sftpUtil;
    
    private static final Logger log = LoggerFactory.getLogger(SftpUpload.class.getName());
    
    /**
     * @Title: uploadToSftp
     * @Description: 上傳文件到Sftp工具類
     * @param file 前台上傳的文件
     * @param model 文件夾名
     * @return 返回上傳後訪問路徑
     * @author: 月夜流心
     */
    public String uploadToSftp(MultipartFile file,String model) {
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd");
        String date =sdf.format(new Date()) + "/";
        try {
            boolean upload = sftpUtil.upload(file.getInputStream(), file.getOriginalFilename() ,"/root/fileUpload");
            if(!upload) {
                return null;
            }
        } catch (IOException e) {
            log.error(e.getMessage());
            return null;
        }
        return  "/root/fileUpload" + file.getOriginalFilename();
    }
    
}

工具类(需要注入,否则第一次使用巨慢)

sftp工具类

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Properties;
import java.util.Vector;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jcraft.jsch.Session;
import com.jcraft.jsch.SftpATTRS;
import com.jcraft.jsch.SftpException;

/**
 * sftp上传下载工具类
 */
public class SftpUtil {

	//ip port username password
	private static final String  SFTP_IP = "127.0.0.1";
	private static final Integer SFTP_PORT = 22;
	private static final String  SFTP_USERNAME = "root";
	private static final String  SFTP_PASSNM = "test123.";

	private static final Logger log = LoggerFactory.getLogger(SftpUtil.class.getName());

	/**
	 * session
	 */
	private Session session;
	/**
	 * 通道
	 */
	private ChannelSftp channel;

	/**
	 * 规避多线程并发不断开问题
	 */
	private static ThreadLocal<SftpUtil> sftpLocal = new ThreadLocal<>();

	/**
	 * 私有构造方法
	 */
	private SftpUtil() {

	}

	/**
	 * 构造函数 非线程安全,故权限为私有
	 */
	private SftpUtil(String host, Integer port, String username, String password) {
		super();
		init(host, port, username, password);
	}

	/**
	 * 获取本地线程存储的sftp客户端
	 * @return
	 * @throws Exception
	 */
	public static SftpUtil getSftpUtil() {
		SftpUtil sftpUtil = sftpLocal.get();
		if (null == sftpUtil || !sftpUtil.isConnected()) {
			sftpLocal.set(new SftpUtil(SFTP_IP, SFTP_PORT, SFTP_USERNAME, SFTP_PASSNM));
		}
		return sftpLocal.get();
	}

	/**
	 * 获取本地线程存储的sftp客户端
	 * @param host
	 * @param port
	 * @param username
	 * @param password
	 * @return
	 */
	public static SftpUtil getSftpUtil(String host, Integer port, String username, String password) {
		// 该方法需要修改,如果线程本地存储有连接则不会使用新的地址,可以测试使用
		SftpUtil sftpUtil = sftpLocal.get();
		if (null == sftpUtil || !sftpUtil.isConnected()) {
			log.info("建立连接");
			sftpLocal.set(new SftpUtil(host, port, username, password));
		} else {
			log.info("连接已经存在");
		}
		return sftpLocal.get();
	}

	/**
	 * 初始化 创建一个新的 SFTP 通道
	 * @param host
	 * @param port
	 * @param username
	 * @param password
	 */
	private void init(String host, Integer port, String username, String password) {
		try {
			// 场景JSch对象
			JSch jSch = new JSch();
			// jsch.addIdentity(); 私钥
			session = jSch.getSession(username, host, port);

			// 第一次登陆时候提示, (ask|yes|no)
			Properties config = new Properties();
			config.put("StrictHostKeyChecking", "no");
			session.setConfig(config);
			// 设置超时
			//session.setTimeout(3*1000);
			// 设置密码
			session.setPassword(password);
			session.connect();

			// 打开SFTP通道
			channel = (ChannelSftp) session.openChannel("sftp");
			// 建立SFTP通道的连接
			channel.connect();

		} catch (JSchException e) {
			log.error(e.getMessage());
		}
	}

	/**
	 * 是否已连接
	 * @return boolean
	 */
	private boolean isConnected() {
		return null != channel && channel.isConnected();
	}

	/**
	 * 关闭通道
	 */
	public void closeChannel() {
		if (null != channel) {
			try {
				channel.disconnect();
			} catch (Exception e) {
				log.error("关闭SFTP通道发生异常:", e);
			}
		}
		if (null != session) {
			try {
				session.disconnect();
			} catch (Exception e) {
				log.error("SFTP关闭 session异常:", e);
			}
		}
	}

	/**
	 * 释放本地线程存储的sftp客户端
	 */
	public static void release() {
		if (null != sftpLocal.get()) {
			sftpLocal.get().closeChannel();
			sftpLocal.set(null);
		}
	}
/*
	*//**
	 * 列出目录下文件,只列出文件名字,没有类型
	 * @param dir 目录
	 * @return List
	 *//*
	@SuppressWarnings("unchecked")
	public List list(String dir) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
			return null;
		}
		Vector files = null;
		try {
			files = channel.ls(dir);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
		if (null != files) {
			List fileNames = new ArrayList<>();
			for (ChannelSftp.LsEntry file : files) {
				String fileName = file.getFilename();
				if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
					continue;
				}
				fileNames.add(fileName);
			}
			return fileNames;
		}
		return null;
	}

	*//**
	 * 列出文件详情
	 * @param dir
	 * @return List
	 *//*
	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List listDetail(String dir) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
			return null;
		}
		Vector files = null;
		try {
			files = channel.ls(dir);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
		if (null != files) {
			List> fileList = new ArrayList<>();
			for (ChannelSftp.LsEntry next : files) {
				Map map = new HashMap<>();
				String fileName = next.getFilename();
				if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
					continue;
				}
				String size = String.valueOf(next.getAttrs().getSize());
				long mtime = next.getAttrs().getMTime();
				String type = "";
				String longname = String.valueOf(next.getLongname());
				if (longname.startsWith("-")) {
					type = "file";
				} else if (longname.startsWith("d")) {
					type = "dir";
				}
				map.put("name", fileName);
				map.put("size", size);
				map.put("type", type);
				map.put("mtime", timestampToDate(mtime));
				fileList.add(map);
			}
			return fileList;
		}
		return null;
	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public List listDetail(String rootDir, String remotePath) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
			return null;
		}
		Vector files = null;
		try {
			channel.cd(rootDir);
			files = channel.ls(remotePath);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
		if (null != files) {
			List> fileList = new ArrayList<>();
			for (ChannelSftp.LsEntry next : files) {
				Map map = new HashMap<>(16);
				String fileName = next.getFilename();
				if (StringUtils.equals(".", fileName) || StringUtils.equals("..", fileName)) {
					continue;
				}
				String size = String.valueOf(next.getAttrs().getSize());
				long mtime = next.getAttrs().getMTime();
				String type = "";
				String longname = String.valueOf(next.getLongname());
				if (longname.startsWith("-")) {
					type = "file";
				} else if (longname.startsWith("d")) {
					type = "dir";
				}
				map.put("name", fileName);
				map.put("size", size);
				map.put("type", type);
				map.put("mtime", timestampToDate(mtime));
				fileList.add(map);
			}
			return fileList;
		}
		return null;
	}*/
	
//	public static String timestampToDate(long time) {
//        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
//        return sdf.format(time);
//    }

	/**
	 * @param file       上传文件
	 * @param remotePath 服务器存放路径,支持多级目录
	 */
	public void upload(File file, String remotePath) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
		}
		try (FileInputStream fileInputStream = new FileInputStream(file)){
			if (file.isFile()) {
				//服务器要创建的目录
				try {
					createDir(remotePath);
				} catch (Exception e) {
					log.error("創建路徑失敗:" + remotePath);
				}
				channel.cd(remotePath);
				channel.put(fileInputStream, file.getName());
			}
		} catch (FileNotFoundException e) {
			log.error("上传文件没有找到");
		} catch (SftpException e1) {
			log.error("上传ftp服务器错误");
		} catch (IOException e2) {
		    log.error(e2.getMessage());
        } 
	}

	/**
	 * @param file       上传文件
	 * @param remoteName 上传文件名字
	 * @param remotePath 服务器存放路径,支持多级目录
	 */
	public boolean upload(File file, String remoteName, String remotePath) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
		} else {
			try (FileInputStream fileInputStream = new FileInputStream(file)) {
				if (file.isFile()) {
					//服务器要创建的目录
					createDir(remotePath);
					channel.cd(remotePath);
					log.error(remotePath + "  " + remoteName);
					channel.put(fileInputStream, remoteName);
					return true;
				}
			} catch (FileNotFoundException e) {
				log.error(e.getMessage(), "上传文件没有找到");
				return false;
			} catch (SftpException e) {
				log.error(e.getMessage());
				return false;
			} catch (IOException e2) {
	            log.error(e2.getMessage());
	        } 
		}
		return false;
	}

	/**
	 * @param inputStream	上传文件
	 * @param remoteName 	上传文件名字
	 * @param remotePath 	服务器存放路径,支持多级目录
	 */
	public boolean upload(InputStream inputStream, String remoteName, String remotePath) {
		if (channel == null) {
			log.error("获取sftp连接失败,请检查" + SFTP_IP + SFTP_PORT + "@" + SFTP_USERNAME + "" + SFTP_PASSNM + "是否可以访问");
		} else {
			try (InputStream input = inputStream) {
				//服务器要创建的目录
				String rPath = remotePath;
				createDir(rPath);
				channel.cd(remotePath);
				log.info(remotePath + "  " + remoteName);
				channel.put(input, remoteName);
				return true;
			} catch (SftpException | IOException e) {
				log.error(e.getMessage());
				return false;
			}
		}
		return false;
	}

	/**
	 * 下载文件
	 * @param downDir 下载目录
	 * @param src     源文件
	 * @param dst     保存后的文件名称或目录
	 */
	public void downFile(String downDir, String src, String dst) {
		try {
			channel.cd(downDir);
			channel.get(src, dst);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
	}

	public void downFiles(String rootDir, String src, String dst) throws Exception {
		channel.cd(rootDir);
		channel.get(src, dst);
	}

	/**
	 * 下载文件
	 * @param rootDir     服务器路径
	 * @param targetPath 目标路径
	 * @return File
	 */
	public File downFile(String rootDir, String targetPath) {
		OutputStream outputStream = null;
		File file = null;
		try {
			channel.cd(rootDir);
			file = new File(targetPath.substring(targetPath.lastIndexOf("/") + 1));
			outputStream = new FileOutputStream(file);
			channel.get(targetPath, outputStream);
		} catch (SftpException e) {
			log.error(e.getMessage());
			return null;
		} catch (FileNotFoundException e) {
			log.error("找不到需要下载或查看的文件,请检查文件路徑或是ftp服务器");
			return null;
		} finally {
			if (outputStream != null) {
				try {
					outputStream.close();
				} catch (IOException e) {
					log.error(e.getMessage());
				}
			}
		}
		return file;
	}

	@SuppressWarnings("rawtypes")
	public Vector listFile(String rootDir, String remotePath) throws SftpException {
		channel.cd(rootDir);
		return channel.ls(remotePath);
	}

	/**
	 * 列出目录下的文件
	 * @param directory:要列出的目录
	 */
	@SuppressWarnings("rawtypes")
	public Vector listFile(String directory) throws SftpException {
		return channel.ls(directory);
	}

	/**
	 * 删除文件
	 * @param filePath 文件全路径
	 * @throws SftpException SftpException
	 */
	public void deleteFile(String filePath) throws SftpException {
		channel.rm(filePath);
	}

	/**
	 * 创建一个文件目录
	 */
	public void createDir(String createpath) {
		try {
			if (isDirExist(createpath)) {
				this.channel.cd(createpath);
				return;
			}
			String[] pathArry = createpath.split("/");
			StringBuffer filePath = new StringBuffer("/");
			for (String path : pathArry) {
				if ("".equals(path)) {
					continue;
				}
				filePath.append(path).append("/");
				if (isDirExist(filePath.toString())) {
					channel.cd(filePath.toString());
				} else {
					// 建立目录
					channel.mkdir(filePath.toString());
					// 进入并设置为当前目录
					channel.cd(filePath.toString());
				}
			}
			this.channel.cd(createpath);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
	}

	/**
	 * 判断目录是否存在
	 */
	public boolean isDirExist(String directory) {
		boolean isDirExistFlag = false;
		try {
			SftpATTRS sftpATTRS = channel.lstat(directory);
			isDirExistFlag = true;
			return sftpATTRS.isDir();
		} catch (Exception e) {
			if ("no such file".equals(e.getMessage().toLowerCase())) {
				isDirExistFlag = false;
			}
		}
		return isDirExistFlag;
	}

	static String PS = "/";

	/**
	 * This method is called recursively to download the folder content from SFTP
	 * server
	 *
	 * @param sourcePath
	 * @param destinationPath
	 * @throws SftpException
	 */
	@SuppressWarnings("unchecked")
	public void recursiveFolderDownload(String sourcePath, String destinationPath) throws SftpException {
		// Let list of folder content
		Vector<ChannelSftp.LsEntry> fileAndFolderList = channel.ls(sourcePath);
		// Iterate through list of folder content
		for (ChannelSftp.LsEntry item : fileAndFolderList) {
			// Check if it is a file (not a directory).
			if (!item.getAttrs().isDir()) {
				if (
					!(new File(destinationPath + PS + item.getFilename())).exists() || (item.getAttrs()
					.getMTime() > new File(destinationPath + PS + item.getFilename()).lastModified() / 1000)
					) { // Download only if changed later.
					new File(destinationPath + PS + item.getFilename());
					// Download file from source (source filename, destination filename).
					channel.get(sourcePath + PS + item.getFilename(), destinationPath + PS + item.getFilename());
				}
			} else if (!(".".equals(item.getFilename()) || "..".equals(item.getFilename()))) {
				// Empty folder copy.
				new File(destinationPath + PS + item.getFilename()).mkdirs();
				// Enter found folder on server to read its contents and create locally.
				recursiveFolderDownload(sourcePath + PS + item.getFilename(),destinationPath + PS + item.getFilename());
			}
		}
	}

	/**
	 * 文件夹不存在,创建
	 * @param folder 待创建的文件节夹
	 */
	public void createFolder(String folder) {
		SftpATTRS stat = null;
		try {
			stat = channel.stat(folder);
		} catch (SftpException e) {
			log.debug("复制目的地文件夹" + folder + "不存在,创建");
		}
		if (stat == null) {
			try {
				channel.mkdir(folder);
			} catch (SftpException e) {
				log.error("创建失败", e.getCause());
			}
		}
	}

	public InputStream get(String filePath) {
		InputStream inputStream = null;
		try {
			inputStream = channel.get(filePath);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
		return inputStream;
	}

	public void put(InputStream inputStream, String filePath) {
		try {
			channel.put(inputStream, filePath);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}

	}

	@SuppressWarnings({ "rawtypes", "unchecked" })
	public Vector<ChannelSftp.LsEntry> ls(String filePath) {
		Vector ls = null;
		try {
			ls = channel.ls(filePath);
		} catch (SftpException e) {
			log.error(e.getMessage());
		}
		return ls;
	}

	/**
	 * 复制文件夹
	 * @param src  源文件夹
	 * @param desc 目的文件夹
	 */
	public void copy(String src, String desc) {
		// 检查目的文件存在与否,不存在则创建
		this.createDir(desc);
		// 查看源文件列表
		Vector<ChannelSftp.LsEntry> fileAndFolderList = this.ls(src);
		for (ChannelSftp.LsEntry item : fileAndFolderList) {
			if (!item.getAttrs().isDir()) {
				try (
						InputStream tInputStream = this.get(src + PS + item.getFilename());
						ByteArrayOutputStream baos = new ByteArrayOutputStream();
						InputStream nInputStream = new ByteArrayInputStream(baos.toByteArray())
					) {

					byte[] buffer = new byte[1024];
					int len;
					while ((len = tInputStream.read(buffer)) > -1) {
						baos.write(buffer, 0, len);
					}
					baos.flush();
					this.put(nInputStream, desc + PS + item.getFilename());
				} catch (IOException e) {
					log.error(e.getMessage());
				}
				// 排除. 和 ..
			} else if (!(".".equals(item.getFilename()) || "..".equals(item.getFilename()))) {
				// 创建文件,可能不需要
				this.createFolder(desc + PS + item.getFilename());
				//递归复制文件
				copy(src + PS + item.getFilename(), desc + PS + item.getFilename());
			}
		}

	}
}

你可能感兴趣的:(java,sftp)