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