/** * * @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>