java使用sftp文件服务器
2022-04-04 本文已影响0人
HachiLin
在工作中,对接第三方服务时,往往存在文件的传输使用,使用stfp是一种简单有效的方式,可以对文件进行上传和下载。下面是使用sftp文件服务器的demo,可以作为工具类放入项目中,即可简单上手和使用。
- FtpClient.java
public class FtpUtil {
private static final Logger logger = LoggerFactory.getLogger(FtpUtil.class);
public FtpUtil() {
}
public static enum ProxyType {
HTTP;
private ProxyType() {
}
}
public static class FtpDto implements Serializable {
private static final long serialVersionUID = 2610830652396624141L;
private String ip;
private int port;
private String user;
private String password;
private String remoteDir;
private String localFilePathName;
private String remoteFileName;
private FtpUtil.ProxyType proxyType;
private String proxyHost;
private int proxyPort;
public FtpDto() {
}
public String getIp() {
return this.ip;
}
public void setIp(String ip) {
this.ip = ip;
}
public int getPort() {
return this.port;
}
public void setPort(int port) {
this.port = port;
}
public String getUser() {
return this.user;
}
public void setUser(String user) {
this.user = user;
}
public String getPassword() {
return this.password;
}
public void setPassword(String password) {
this.password = password;
}
public String getRemoteDir() {
return this.remoteDir;
}
public void setRemoteDir(String remoteDir) {
this.remoteDir = remoteDir;
}
public String getLocalFilePathName() {
return this.localFilePathName;
}
public void setLocalFilePathName(String localFilePathName) {
this.localFilePathName = localFilePathName;
}
public String getRemoteFileName() {
return this.remoteFileName;
}
public void setRemoteFileName(String remoteFileName) {
this.remoteFileName = remoteFileName;
}
public FtpUtil.ProxyType getProxyType() {
return this.proxyType;
}
public void setProxyType(FtpUtil.ProxyType proxyType) {
this.proxyType = proxyType;
}
public String getProxyHost() {
return this.proxyHost;
}
public void setProxyHost(String proxyHost) {
this.proxyHost = proxyHost;
}
public int getProxyPort() {
return this.proxyPort;
}
public void setProxyPort(int proxyPort) {
this.proxyPort = proxyPort;
}
}
}
- SftpClient.java
public class SftpClient {
/**
* 上传文件
*
* @param ip
* @param port
* @param user
* @param password
* @param localFilePath
* @param remoteDir
* @param remoteFileName
* @param useProxy
*/
public static final String PROXY_HOST = "XXXX";
public static final int PROXY_PORT = XX;
public static void upload(String ip, int port, String user, String password, String localFilePath, String remoteDir,
String remoteFileName, boolean useProxy) {
FtpDto ftpDto = new FtpDto();
ftpDto.setIp(ip);
ftpDto.setPort(port);
ftpDto.setUser(user);
ftpDto.setPassword(password);
if (useProxy) {
ftpDto.setProxyType(ProxyType.HTTP);
ftpDto.setProxyHost(PROXY_HOST);
ftpDto.setProxyPort(PROXY_PORT);
}
ftpDto.setRemoteDir(remoteDir);
ftpDto.setLocalFilePathName(localFilePath);
ftpDto.setRemoteFileName(remoteFileName);
SftpUtil.upload(ftpDto);
}
/**
* 下载文件
*
* @param ip
* @param port
* @param user
* @param password
* @param localFilePath
* @param remoteDir
* @param remoteFileName
* @param useProxy
*/
public static void download(String ip, int port, String user, String password, String localFilePath,
String remoteDir, String remoteFileName, boolean useProxy) {
FtpDto ftpDto = new FtpDto();
ftpDto.setIp(ip);
ftpDto.setPort(port);
ftpDto.setUser(user);
ftpDto.setPassword(password);
if (useProxy) {
ftpDto.setProxyType(ProxyType.HTTP);
ftpDto.setProxyHost(PROXY_HOST);
ftpDto.setProxyPort(PROXY_PORT);
}
ftpDto.setRemoteDir(remoteDir);
ftpDto.setLocalFilePathName(localFilePath);
ftpDto.setRemoteFileName(remoteFileName);
SftpUtil.download(ftpDto);
}
}
-
SftpUtil.java
pom依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
</dependency>
import com.jcraft.jsch.*;
public class SftpUtil {
private static int timeout = 60000;
private static final Logger logger = LoggerFactory.getLogger(SftpUtil.class);
private static ChannelItem getChannel(FtpDto ftpDto) throws Exception {
JSch jsch = new JSch();
Session session = jsch.getSession(ftpDto.getUser(), ftpDto.getIp(), ftpDto.getPort());
session.setPassword(ftpDto.getPassword());
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
session.setConfig(config);
session.setTimeout(timeout);
if (!StringUtils.isBlank(ftpDto.getProxyHost())) {
ProxyHTTP proxy = new ProxyHTTP(ftpDto.getProxyHost(), ftpDto.getProxyPort());
session.setProxy(proxy);
}
session.connect();
Channel channel = session.openChannel("sftp");
channel.connect();
ChannelItem channelItem = new ChannelItem();
channelItem.setChannel((ChannelSftp) channel);
channelItem.setSession(session);
return channelItem;
}
private static void closeChannel(ChannelItem channelItem) {
try {
if (channelItem.getSession() != null) {
channelItem.getSession().disconnect();
}
} catch (Exception e1) {
logger.warn("退出SFTP管道异常");
}
try {
if (channelItem.getChannel() != null) {
channelItem.getChannel().disconnect();
}
} catch (Exception e1) {
logger.warn("退出SFTP管道异常");
}
}
public static void upload(FtpDto ftpDto) {
upload(ftpDto, null);
}
public static void upload(FtpDto ftpDto, String capSubCodePath) {
logger.info("开始SFTP文件上传:{}", ftpDto.toString());
ChannelSftp chSftp = null;
ChannelItem channelItem = null;
InputStream is = null;
try {
channelItem = SftpUtil.getChannel(ftpDto);
chSftp = (ChannelSftp) channelItem.getChannel();
try {
if (StringUtils.isNotEmpty(capSubCodePath)) {
if (!isDirExist(chSftp, capSubCodePath)) {
chSftp.mkdir(capSubCodePath);
}
}
if (!isDirExist(chSftp, ftpDto.getRemoteDir())) {
createDir(chSftp, ftpDto.getRemoteDir());
}
logger.info("创建目录成功:{}", ftpDto.getRemoteDir());
} catch (SftpException e) {
logger.error("创建目录失败:{}", ftpDto.getRemoteDir(), e);
}
String upPath = ftpDto.getRemoteDir();
if (!(upPath.endsWith(File.separator) || upPath.endsWith("/"))) {
upPath = upPath.concat(File.separator);
}
upPath = upPath.concat(ftpDto.getRemoteFileName());
OutputStream out = chSftp.put(upPath, ChannelSftp.OVERWRITE);
byte[] buff = new byte[1024 * 256];
int read;
if (out != null) {
is = new FileInputStream(ftpDto.getLocalFilePathName());
do {
read = is.read(buff, 0, buff.length);
if (read > 0) {
out.write(buff, 0, read);
}
out.flush();
} while (read >= 0);
}
} catch (Exception e) {
logger.error("SFTP文件上传失败", e);
throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { ftpDto.getRemoteFileName() + "文件上传失败" }, e.getMessage());
} finally {
if (chSftp != null) {
try {
chSftp.quit();
} catch (Exception e) {
logger.warn("退出SFTP管道异常");
}
}
if (is != null) {
try {
is.close();
} catch (Exception e) {
logger.warn("关闭InputStream异常");
}
}
closeChannel(channelItem);
}
logger.info("成功SFTP文件上传:{}", ftpDto.getLocalFilePathName());
}
/**
* 批量文件上传
*
* @param ftpDto
* @return
* @throws Exception
*/
public static boolean batchUploadFile(List<FtpDto> ftpDtoList) throws Exception {
ChannelItem channelItem = SftpUtil.getChannel(ftpDtoList.get(0));
try {
ChannelSftp chSftp = (ChannelSftp) channelItem.getChannel();
boolean flag = batchUploadFile(chSftp, ftpDtoList);
return flag;
} catch (Exception e) {
logger.error("SftpUtil.batchUploadFile上传异常:", e);
} finally {
closeChannel(channelItem);
}
return false;
}
/**
* 批量文件上传
*
* @param ftpDto
* @return
*/
private static boolean batchUploadFile(ChannelSftp chSftp, List<FtpDto> ftpDtoList) {
boolean doneFlag = false;
try {
for (FtpDto ftpDto : ftpDtoList) {
boolean flag = uploadFile(chSftp, ftpDto);
if (!flag) {
doneFlag = false;
logger.error("SftpUtil.batchUploadFile上传失败:FilePathName:{}", ftpDto.getLocalFilePathName());
break;
} else {
doneFlag = true;
logger.info("SftpUtil.batchUploadFile上传成功:FilePathName:{}", ftpDto.getLocalFilePathName());
}
}
} catch (Exception e) {
doneFlag = false;
logger.error("SftpUtil.batchUploadFile上传异常:", e);
}
return doneFlag;
}
private static boolean uploadFile(ChannelSftp chSftp, FtpDto ftpDto) {
InputStream is = null;
try {
if (!isDirExist(chSftp, ftpDto.getRemoteDir())) {
createDir(chSftp, ftpDto.getRemoteDir());
}
OutputStream out = chSftp.put(ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()), ChannelSftp.OVERWRITE);
byte[] buff = new byte[1024 * 256];
int read;
if (out != null) {
is = new FileInputStream(ftpDto.getLocalFilePathName());
do {
read = is.read(buff, 0, buff.length);
if (read > 0) {
out.write(buff, 0, read);
}
out.flush();
} while (read >= 0);
}
return true;
} catch (Exception e) {
logger.error("SftpUtil文件上传上传异常:", e);
throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { ftpDto.getRemoteFileName() + "文件上传失败" }, e.getMessage());
} finally {
if (chSftp != null) {
try {
chSftp.quit();
} catch (Exception e) {
logger.warn("退出SFTP管道异常");
}
}
if (is != null) {
try {
is.close();
} catch (Exception e) {
logger.warn("关闭InputStream异常");
}
}
}
}
private static void createDir(ChannelSftp chSftp, String directory) {
try {
if (directory == null) {
return;
}
if (isDirExist(chSftp, directory)) {
chSftp.cd(directory);
}
String pathArry[] = directory.split("/");
StringBuffer filePath = new StringBuffer("/");
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
if (isDirExist(chSftp, filePath.toString())) {
logger.info("进入并设置为当前目录0:{}", filePath.toString());
chSftp.cd(filePath.toString());
} else {
// 建立目录
logger.info("建立目录:{}", filePath.toString());
chSftp.mkdir(filePath.toString());
// 进入并设置为当前目录
logger.info("进入并设置为当前目录:{}", filePath.toString());
chSftp.cd(filePath.toString());
}
}
chSftp.cd(directory);
} catch (SftpException e) {
logger.error("创建目录失败:{}", directory, e);
}
}
private static boolean isDirExist(ChannelSftp chSftp, String directory) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = chSftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
public static void download(FtpDto ftpDto) {
logger.info("开始SFTP文件下载:{}", ftpDto.toString());
ChannelSftp chSftp = null;
ChannelItem channelItem = null;
OutputStream out = null;
try {
channelItem = SftpUtil.getChannel(ftpDto);
chSftp = (ChannelSftp) channelItem.getChannel();
InputStream is = chSftp.get(ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()));
out = new FileOutputStream(ftpDto.getLocalFilePathName());
byte[] buff = new byte[1024 * 2];
int read;
if (is != null) {
do {
read = is.read(buff, 0, buff.length);
if (read > 0) {
out.write(buff, 0, read);
}
out.flush();
} while (read >= 0);
}
} catch (Exception e) {
logger.warn("SFTP文件下载失败:" + ftpDto.getRemoteDir().concat(ftpDto.getRemoteFileName()), e);
throw new ServiceException(CommonErrorCode.ERROR_FILE_UPLOAD, e, new String[] { "文件下载失败" }, ftpDto.getRemoteFileName());
} finally {
if (chSftp != null) {
try {
chSftp.quit();
} catch (Exception e) {
logger.warn("退出SFTP管道异常");
}
}
if (out != null) {
try {
out.close();
} catch (Exception e) {
logger.warn("关闭OutputStream异常");
}
}
closeChannel(channelItem);
}
logger.info("成功SFTP文件下载:{}", ftpDto.getLocalFilePathName());
}
static class ChannelItem {
Session session;
Channel channel;
public Session getSession() {
return session;
}
public void setSession(Session session) {
this.session = session;
}
public Channel getChannel() {
return channel;
}
public void setChannel(Channel channel) {
this.channel = channel;
}
}
public static class MyProgressMonitor implements SftpProgressMonitor {
private long transfered;
public MyProgressMonitor(long transfered) {
this.transfered = transfered;
}
@Override
public boolean count(long count) {
transfered = transfered + count;
return true;
}
@Override
public void end() {
}
@Override
public void init(int op, String src, String dest, long max) {
}
}
}