首页 > 代码库 > sftp工具类

sftp工具类

/**
 * 
 * @ClassName:SftpFileServiceImpl
 * @Description:SFTP文件服务
 */
@FileServiceModel(FileServiceType.SFTP)
public class SftpFileServiceImpl implements FileService {

	private static Logger logger = LoggerFactory
			.getLogger(SftpFileServiceImpl.class);

	public SftpFileServiceImpl() {
		logger.debug("FileService Class : SftpFileServiceImpl");
	}

	/**
	 * 临时目录,用于存放从SFTP下载的临时文件
	 */
	private File tempDir;

	/**
	 * 
	 * @Title:existFile
	 * @Description:(判断文件是否存在)
	 * @param path
	 * @return
	 * @throws Exception
	 */
	@Override
	public boolean existFile(String path) throws Exception {
		Assert.notNull(path,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "path"));

		Session session = null;
		ChannelSftp channelSftp = null;
		boolean exist = false;

		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
		} catch (Exception e) {
			throw e;
		}
		// 切换路径
		File file = new File(path);
		Vector<LsEntry> fileList = null;
		try {
			logger.info("existFile file.getParent():" + file.getParent());
			
			fileList = this.listFiles(channelSftp, file.getParent());
			if (fileList != null) {
				for (LsEntry object : fileList) {
					if ((object.getFilename().equals(file.getName()))) {
						logger.info("existFile path:" + path);
						exist = true;
						break;
					}
				}
			}
			
		} catch (Exception e) {
			throw e;
		} finally {
			this.closeChannel(channelSftp);
			this.closeSession(session);
		}
		logger.info("existFile:" + exist);
		return exist;
	}

	/**
	 * 
	 * @Title:getStream
	 * @Description:(获取{@link InputStream}文件输入流,若为远程文件服务,将复制到本地临时文件夹)
	 * @param path 文件绝对路径
	 * @return
	 * @throws Exception

	 */
	@Override
	public InputStream getStream(String path) throws Exception {
		Assert.notNull(path,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "path"));

		File tmpFile = null;
		FileInputStream fis = null;
		Session session = null;
		ChannelSftp channelSftp = null;
		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
			// 切换路径
			File file = new File(path);
			channelSftp.cd(file.getParent());
			// 获取临时文件夹
			StringBuilder sb = new StringBuilder(
					PropertiesUtils.getProperty("file.sftp.tempDir"));
			if (sb.lastIndexOf("/") != sb.length() - 1)
				sb.append("/");
			tempDir = new File(sb.toString());
			if (!tempDir.exists())
				tempDir.mkdirs();

			// 将文件先从SFTP下载到临时文件夹,然后返回临时文件夹的File对象
			tmpFile = new File(tempDir + File.separator + file.getName());
			InputStream inputStream = channelSftp.get(file.getName());
			FileUtils.copyInputStreamToFile(inputStream, tmpFile);

			IOUtils.closeQuietly(inputStream);
			fis = new FileInputStream(tmpFile);
			return IOUtils.toBufferedInputStream(fis);
		} catch (Exception e) {
			throw e;
		} finally {
			this.closeChannel(channelSftp);
			this.closeSession(session);
			IOUtils.closeQuietly(fis);
		}
	}

	/**
	 * 
	 * @Title:getFile
	 * @Description:获取{@link File}文件对象,若为远程文件服务,将复制到本地临时文件夹
	 * @param path 文件绝对路径
	 * @return
	 * @throws Exception

	 */
	@Override
	public File getFile(String path) throws Exception {
		Assert.notNull(path,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "path"));

		File tmpFile = null;
		Session session = null;
		ChannelSftp channelSftp = null;
		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
			// 切换路径
			File file = new File(path);
			channelSftp.cd(file.getParent());
			// 获取临时文件夹
			StringBuilder sb = new StringBuilder(
					PropertiesUtils.getProperty("file.sftp.tempDir"));
			if (sb.lastIndexOf("/") != sb.length() - 1)
				sb.append("/");
			tempDir = new File(sb.toString());
			if (!tempDir.exists())
				tempDir.mkdirs();

			// 将文件先从FTP下载到临时文件夹,然后返回临时文件夹的File对象
			tmpFile = new File(tempDir + File.separator + file.getName());
			InputStream inputStream = channelSftp.get(file.getName());
			FileUtils.copyInputStreamToFile(inputStream, tmpFile);

			IOUtils.closeQuietly(inputStream);
			return tmpFile;
		} catch (Exception e) {
			throw e;
		} finally {
			this.closeChannel(channelSftp);
			this.closeSession(session);
		}
	}

	/**
	 * 
	 * @Title:getString
	 * @Description:获取{@link String}文件内容字符串
	 * @param path 文件绝对路径
	 * @return
	 * @throws Exception

	 */
	@Override
	public String getString(String path) throws Exception {
		Assert.notNull(path,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "path"));

		Session session = null;
		ChannelSftp channelSftp = null;
		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
			// 切换路径
			File file = new File(path);
			channelSftp.cd(file.getParent());
			InputStream inputStream = channelSftp.get(file.getName());
			return IOUtils.toString(inputStream);
		} catch (Exception e) {
			throw e;
		} finally {
			this.closeChannel(channelSftp);
			this.closeSession(session);
		}
	}

	/**
	 * 
	 * @Title:deleteFile
	 * @Description:删除文件
	 * @param path 文件绝对路径
	 * @return
	 * @throws Exception

	 */
	@Override
	public boolean deleteFile(String path) throws Exception {
		Assert.notNull(path,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "path"));

		Session session = null;
		ChannelSftp channelSftp = null;
		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
			// 切换路径
			File file = new File(path);
			channelSftp.cd(file.getParent());
			channelSftp.rm(file.getName());
			if (this.existFile(path)) {
				return false;
			}
			return true;
		} catch (Exception e) {
			throw e;
		} finally {
			this.closeChannel(channelSftp);
			this.closeSession(session);
		}
	}

	/**
	 * 
	 * @Title:addFile
	 * @Description:(添加文件)
	 * @param targetPath   目标文件绝对路径 
	 * @param inputStream 输入文件流
	 * @param override  是否覆盖已有文件
	 * @throws Exception

	 */
	@Override
	public void addFile(String targetPath, InputStream inputStream,
			boolean override) throws Exception {
		Assert.notNull(targetPath, String.format(
				FileServiceUtils.EMPTY_PARAM_MESSAGE, "targetPath"));
		Assert.notNull(inputStream, String.format(
				FileServiceUtils.EMPTY_PARAM_MESSAGE, "inputStream"));

		// 判断是否需要覆盖文件写入
		if (!override) {
			if (existFile(targetPath)) {
				throw new FileExistsException("File " + targetPath
						+ " exists !");
			}
		}

		Session session = null;
		ChannelSftp channelSftp = null;
		OutputStream outputStream = null;
		try {
			session = this.getSession();
			channelSftp = this.getChannelSftp(session);
			File targetFile = new File(targetPath);
			// 尝试切换到指定目录,若成功则继续,若失败则创建后切换
			if (!changeWorkingDirectory(channelSftp, targetFile.getParent())) {
				// 创建目录
				channelSftp.mkdir(targetFile.getParent());
				// 创建完成后切换到指定目录
				channelSftp.cd(targetFile.getParent());
			}
			logger.info("addFile pwd:" + channelSftp.pwd());
			outputStream = channelSftp.put(targetFile.getName());
			// 向SFTP服务器复制文件
			IOUtils.copy(inputStream, outputStream);
		} catch (Exception e) {
			throw e;
		} finally {
			IOUtils.closeQuietly(outputStream);
			this.closeChannel(channelSftp);
			this.closeSession(session);
		}
	}

	/**
	 * 
	 * @Title:addFile
	 * @Description:添加文件
	 * @param targetPath 目标文件绝对路径
	 * @param srcFile 源文件文件对象(本地文件)
	 * @param override 是否覆盖已有文件
	 * @throws Exception

	 */
	@Override
	public void addFile(String targetPath, File srcFile, boolean override)
			throws Exception {
		Assert.notNull(targetPath, String.format(
				FileServiceUtils.EMPTY_PARAM_MESSAGE, "targetPath"));
		Assert.notNull(srcFile,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "srcFile"));
		Assert.isTrue(srcFile.exists(), "The file ‘" + srcFile.getPath()
				+ "‘ is not exists !");

		// 判断是否需要覆盖文件写入
		if (!override) {
			if (existFile(targetPath)) {
				throw new FileExistsException("File " + targetPath
						+ " exists !");
			}
		}

		InputStream inputStream = null;
		try {
			inputStream = FileUtils.openInputStream(srcFile);
			this.addFile(targetPath, inputStream, override);
		} catch (Exception e) {
			throw e;
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
	}

	/**
	 * 
	 * @Title:addFile
	 * @Description:添加文件
	 * @param targetPath 目标文件绝对路径
	 * @param str  输入文件字符串内容
	 * @param override  是否覆盖已有文件
	 * @throws Exception

	 */
	@Override
	public void addFile(String targetPath, String str, boolean override)
			throws Exception {
		Assert.notNull(targetPath, String.format(
				FileServiceUtils.EMPTY_PARAM_MESSAGE, "targetPath"));
		Assert.notNull(str,
				String.format(FileServiceUtils.EMPTY_PARAM_MESSAGE, "str"));

		// 判断是否需要覆盖文件写入
		if (!override) {
			if (existFile(targetPath)) {
				throw new FileExistsException("File " + targetPath
						+ " exists !");
			}
		}

		InputStream inputStream = null;
		try {
			inputStream = IOUtils.toInputStream(str);
			this.addFile(targetPath, inputStream, override);
		} catch (Exception e) {
			throw e;
		} finally {
			IOUtils.closeQuietly(inputStream);
		}
	}

	/**
	 * 
	 * @Title:getSession
	 * @Description:(获取session)
	 * @return
	 * @throws Exception
	
	 */
	private Session getSession() throws Exception {
		String addressStr = PropertiesUtils.getProperty("file.sftp.address");
		Assert.notNull(
				addressStr,
				"The property of config [file.sftp.address] is empty ! Please check and try again !");
		String[] address = addressStr.split(":");
		JSch jsch = new JSch();
		Session session = null;
		session = jsch.getSession(
				PropertiesUtils.getProperty("file.sftp.username"), address[0],
				Integer.parseInt(address[1]));
		session.setPassword(PropertiesUtils.getProperty("file.sftp.password"));
		session.setConfig("StrictHostKeyChecking", "no");
		session.connect();
		if (!session.isConnected()) {
			throw new IllegalArgumentException(
					"connect : Failed to connect address -> " + addressStr);
		}
		return session;
	}

	/**
	 * 
	 * @Title:getChannelSftp
	 * @Description:(获取ChannelSftp)
	 * @param session
	 * @return
	 * @throws Exception

	 */
	private ChannelSftp getChannelSftp(Session session) throws Exception {
		Channel channel = session.openChannel("sftp");
		channel.connect();
		ChannelSftp channelSftp = (ChannelSftp) channel;
		channelSftp.cd(PropertiesUtils.getProperty("file.sftp.dist"));
		if (!channelSftp.isConnected()) {
			throw new Exception("getChannelSftp : Failed to get ChannelSftp");
		}
		return channelSftp;
	}

	/**
	 * 
	 * @Title:closeChannel
	 * @Description:(关闭channel)
	 * @param channel

	 */
	private void closeChannel(Channel channel) {
		if (channel != null && channel.isConnected()) {
			channel.disconnect();
		}
		channel = null;
	}

	/**
	 * 
	 * @Title:closeSession
	 * @Description:(关闭session)
	 * @param session

	 */
	private void closeSession(Session session) {
		if (session != null && session.isConnected()) {
			session.disconnect();
		}
		session = null;
	}

	private boolean changeWorkingDirectory(ChannelSftp channelSftp,
			String pathname) throws IOException {
		try {
			channelSftp.cd(pathname);
		} catch (SftpException e) {
			// e.printStackTrace();
			return false;
		}
		return true;
	}

	@SuppressWarnings("unchecked")
	private Vector<LsEntry> listFiles(ChannelSftp channelSftp, String path) {
		Vector<LsEntry> vector = null;
		try {
			vector = channelSftp.ls(path);
		} catch (SftpException e) {
			// logger.info("listFiles ---failed", e);
			vector = null;
		}
		return vector;

	}
}
public interface FileServiceUtils {

	/**
	 * 空参数错误提示信息
	 */
	public static String EMPTY_PARAM_MESSAGE = "The param ‘%s‘ is empty ! Please check the param and try again.";

	/**
	 * 文件编码格式:UTF-8
	 */
	public static String FILE_CHARSET_UTF8 = "UTF-8";

	/**
	 * 默认文件编码格式
	 */
	public static String DEFAULT_FILE_CHARSET = FILE_CHARSET_UTF8;

}

  

public enum FileServiceType {
	/**
	 * 磁盘文件服务
	 */
	DISK, 
	/**
	 * FTP文件服务
	 */
	FTP,
	/**
	 * SFTP文件服务
	 */
	SFTP
}

  

public interface FileService {

    /**
     * 
     * @Title:existFile
     * @Description:判断文件是否存在
     * @param path
     *            文件绝对路径
     * @return
     * @throws Exception
*/
    public boolean existFile(String path) throws Exception;

    /**
     * 
     * @Title:getStream
     * @Description:获取{@link InputStream}文件输入流,若为远程文件服务,将复制到本地临时文件夹
     * @param path
     *            文件绝对路径
     * @return
     * @throws Exception
*/
    public InputStream getStream(String path) throws Exception;

    /**
     * 
     * @Title:getFile
     * @Description:获取{@link File}文件对象,若为远程文件服务,将复制到本地临时文件夹
     * @param path
     *            文件绝对路径
     * @return
     * @throws Exception
     */
    public File getFile(String path) throws Exception;

    /**
     * 
     * @Title:getString
     * @Description:获取{@link String}文件内容字符串
     * @param path
     *            文件绝对路径
     * @return
     * @throws Exception
    */
    public String getString(String path) throws Exception;

    /**
     * 
     * @Title:deleteFile
     * @Description:删除文件
     * @param path
     *            文件绝对路径
     * @return
     * @throws Exception
*/
    public boolean deleteFile(String path) throws Exception;

    /**
     * 
     * @Title:addFile
     * @Description:添加文件
     * @param targetPath
     *            目标文件绝对路径
     * @param inputStream
     *            输入文件流
     * @param override
     *            是否覆盖已有文件
     * @throws Exception
 */
    public void addFile(String targetPath, InputStream inputStream, boolean override) throws Exception;

    /**
     * 
     * @Title:addFile
     * @Description:添加文件
     * @param targetPath
     *            目标文件绝对路径
     * @param srcFile
     *            源文件文件对象(本地文件)
     * @param override
     *            是否覆盖已有文件
     * @throws Exception
   */
    public void addFile(String targetPath, File srcFile, boolean override) throws Exception;

    /**
     * 
     * @Title:addFile
     * @Description:添加文件
     * @param targetPath
     *            目标文件绝对路径
     * @param str
     *            输入文件字符串内容
     * @param override
     *            是否覆盖已有文件
     * @throws Exception
    */
    public void addFile(String targetPath, String str, boolean override) throws Exception;

}
     
<jsch_version>0.1.54</jsch_version>
<!--
SFTP jsch --> <dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>${jsch_version}</version> </dependency>

 

sftp工具类