import com.jcraft.jsch.Channel;
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;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.multipart.MultipartFile;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import java.util.Properties;
/**
*类描述 .
*
**/
@Slf4j
public class SftpUtil {
/**
* 连接sftp服务器
*
* @param host 主机
* @param port 端口
* @param username 用户名
* @param password 密码
* @return
*/
public ChannelSftp connect(String host, int port, String username, String password) {
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
jsch.getSession(username, host, port);
Session sshSession = jsch.getSession(username, host, port);
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
log.info("SFTP Session connected.");
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
log.info("Connected to " + host);
} catch (Exception e) {
log.error(e.getMessage());
}
return sftp;
}
/**
* 创建多级目录
* @return
*/
private boolean createDirs(String dirPath, ChannelSftp sftp) {
if (dirPath != null && !dirPath.isEmpty() && sftp != null) {
String[] dirs = Arrays.stream(dirPath.split("/"))
.filter(StringUtils::isNotBlank)
.toArray(String[]::new);
for (String dir : dirs) {
try {
sftp.cd(dir);
log.info("Change directory {}", dir);
} catch (Exception e) {
try {
sftp.mkdir(dir);
log.info("Create directory {}", dir);
} catch (SftpException e1) {
log.error("Create directory failure, directory:{}", dir, e1);
e1.printStackTrace();
}
try {
sftp.cd(dir);
log.info("Change directory {}", dir);
} catch (SftpException e1) {
log.error("Change directory failure, directory:{}", dir, e1);
e1.printStackTrace();
}
}
}
return true;
}
return false;
}
/**
* 上传文件
*
* @param sftp 连接
* @param targetPath 上传的目录 以“/”结尾
* @param file 要上传的文件
*/
public String upload(ChannelSftp sftp, String rootPath, String targetPath, MultipartFile file) throws Exception {
try {
//校验文件
FileUtil fileUtil = new FileUtil();
boolean flag = fileUtil.fileVerify(file);
if (!flag) {
log.error("上传文件有误");
throw new Exception("上传文件有误");
}
sftp.cd(rootPath);
log.info("Change path to {}", rootPath);
if (StringUtils.isNotEmpty(targetPath)) {
boolean dirs = createDirs(targetPath, sftp);
if (!dirs) {
log.error("创建文件夹失败,路径为:{}", targetPath);
throw new Exception("上传文件失败");
}
}
String fileName = file.getOriginalFilename();
fileName = DateUtils.getCurrentDateTimeNoBlank()+fileName;
InputStream inputStream = file.getInputStream();
sftp.put(inputStream, fileName);
log.info("上传文件成功");
StringBuffer sb = new StringBuffer();
if (StringUtils.isNotEmpty(targetPath)) {
String[] dirs = Arrays.stream(targetPath.split("/"))
.filter(StringUtils::isNotBlank)
.toArray(String[]::new);
for (String dir : dirs) {
sb.append("/").append(dir);
}
}
return sb + "/" + fileName;
} catch (Exception e) {
log.error("上传文件失败,目标路径为:{}", targetPath, e);
throw new Exception("上传文件失败");
} finally {
this.disconnect(sftp);
}
}
/**
* 下载文件
*
* @param sftp 连接
* @param targetPath
*/
public File download(ChannelSftp sftp, String rootPath, String targetPath) throws Exception {
OutputStream outputStream = null;
try {
sftp.cd(rootPath);
File file = new File(targetPath.substring(targetPath.lastIndexOf("/") + 1));
outputStream = new FileOutputStream(file);
sftp.get(targetPath, outputStream);
log.info("下载文件成功");
return file;
} catch (Exception e) {
log.error("下载文件失败", e.getMessage(), e);
throw new Exception("下载失败");
} finally {
if (outputStream != null) {
outputStream.close();
}
this.disconnect(sftp);
}
}
/**
* 删除文件
* @param sftp
* @param rootPath
* @param targetPath
*/
public boolean delete(ChannelSftp sftp, String rootPath, String targetPath) throws Exception {
try {
sftp.cd(rootPath);
SftpATTRS lstat = sftp.lstat(rootPath + "/" + targetPath);
sftp.rm(targetPath);
log.info("删除文件成功");
return true;
} catch (SftpException e) {
log.error("文件:{}不存在", targetPath);
throw new Exception("文件不存在");
} catch (Exception e) {
log.error("删除失败,目标路径:{}", targetPath, e);
throw new Exception("删除失败");
} finally {
this.disconnect(sftp);
}
}
/**
* 关闭连接
* @param sftp
*/
public void disconnect(ChannelSftp sftp) {
try {
if (sftp != null) {
if (sftp.isConnected()) {
sftp.disconnect();
} else if (sftp.isClosed()) {
log.info("sftp is closed already");
}
if (null != sftp.getSession()) {
sftp.getSession().disconnect();
}
}
} catch (JSchException e) {
log.error(e.getMessage());
}
}
}
引用:
@Slf4j
@Service
public class ClaimUploadServiceImpl extends ServiceImpl<ClaimClaimInfoMapper, ClaimClaimInfo> implements ClaimUploadService {
@Value("${sftp.client.host}")
private String host;
@Value("${sftp.client.port}")
private int port;
@Value("${sftp.client.username}")
private String username;
@Value("${sftp.client.password}")
private String password;
@Value("${sftp.client.rootPath}")
private String rootPath;
@Override
public Result uploadClaim(ClaimUploadDto claimUploadDto) {
try{
SftpUtil sf = new SftpUtil();
ChannelSftp sftp = sf.connect(host, port, username, password);
String url = sf.upload(sftp, rootPath, claimUploadDto.getTargetPath(), claimUploadDto.getFile());
url = "/images" + url;
return Result.success(url);
}
catch (Exception e){
log.error("图片上传异常:{}", e.getMessage());
return Result.failure("500", e.getMessage());
}
}
}