## 依赖
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.55</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-compress</artifactId>
<version>1.21</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>
## 工具类SftpUtils
@Component
@Slf4j
public class SftpUtils {
public ChannelSftp sftp;
public boolean isReady = false;
public FtpConfig config;
public Session sshSession;
@Data
private class FtpConfig {
private String server;
private String port;
private String username;
private String password;
private String encoding;
}
/**
* 连接sftp服务器
*/
public SftpUtils(String server, String port, String username, String password, String encoding) {
config = new FtpConfig();
config.setServer(server);
config.setPort(port);
config.setUsername(username);
config.setPassword(password);
config.setEncoding(encoding);
log.info("server = {}, port = {}, username = {}, password = {}", server, port, username, password);
}
public void setReady() throws Exception {
try {
if (!isReady) {
JSch jsch = new JSch();
sshSession = jsch.getSession(config.getUsername(), config.getServer(), Integer.parseInt(config.getPort()));
log.info("Session created.");
sshSession.setPassword(config.getPassword());
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
isReady = true;
log.info("Session is ready.");
}
if (sshSession != null && !sshSession.isConnected()) {
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
Class<ChannelSftp> c = ChannelSftp.class;
Field f = c.getDeclaredField("server_version");
f.setAccessible(true);
f.set(sftp, 2);
sftp.setFilenameEncoding(config.getEncoding());
log.info("Session is connected.");
}
} catch (Exception e) {
this.close();
log.error("sftp连接服务器出错,host:" + config.getServer(), e);
throw e;
}
}
/**
* 判断目录是否存在
* @param directory
* @return
*/
public boolean isDirExist(String directory, ChannelSftp sftp)
{
boolean isDirExistFlag = false;
try
{
sftp.cd(directory);
isDirExistFlag = true;
}
catch (Exception e)
{
if (e.getMessage().equalsIgnoreCase("no such file"))
{
isDirExistFlag = false;
}
}finally {
return isDirExistFlag;
}
}
/**
* 创建文件夹
*/
public void createFolder(String sourceFolder){
try {
sftp.mkdir(sourceFolder);
}catch (SftpException e){
e.printStackTrace();
}
}
/**
* 设置编码格式
*/
public void setEncoding(){
try {
Class cl = sftp.getClass();
Field field = cl.getDeclaredField("server_version");
field.setAccessible(true);
field.set(sftp,2);
sftp.setFilenameEncoding("GBK");
}catch (Exception e){
e.printStackTrace();
}
}
/**
* 上传文件
* @param filePath
* @param fileName
* @param file
* @return
* @throws Exception
*/
public boolean uploadFile(String filePath, String fileName, File file) throws Exception {
log.info("directory:{},downloadFile:{},saveFile:{}", filePath, fileName, file);
try {
setReady();
// sftp.cd(filePath);
sftp.put(new FileInputStream(file), fileName);
return true;
} catch (Exception e) {
log.error("sftp上传文件出错,fileName:" + fileName, e);
throw e;
}
}
/**
* 列出目录下的文件
*
* @param directory 文件所在目录
* @throws Exception
*/
public List<String> listFiles(String directory) throws Exception {
log.info("directory:{}", directory);
setReady();
Vector<ChannelSftp.LsEntry> vector = sftp.ls(directory);
if (vector.isEmpty()) {
return Collections.emptyList();
}
return vector.stream().map(ChannelSftp.LsEntry::getFilename).collect(Collectors.toList()).stream().filter(file -> !".".equals(file) && !"..".equals(file)).collect(Collectors.toList());
}
/**
* 删除文件
*
* @param directory
* 要删除文件所在目录
* @param deleteFile
* 要删除的文件
* @param sftp
*/
public void delete(String directory, String deleteFile, ChannelSftp sftp) {
try {
sftp.cd(directory);
sftp.rm(deleteFile);
} catch (Exception e) {
e.printStackTrace();
}
}
}
## 压缩工具类
public class ZipUtil {
/**
* 将文件压缩成zip
*
* @param sourceFile 源文件或目录,如:archive.tar
* @param targetFile 目标文件,如:archive.tar.zip
*/
public static void compress(String sourceFile, String targetFile) {
long d1 = System.currentTimeMillis();
try (OutputStream fos = new FileOutputStream(targetFile);
OutputStream bos = new BufferedOutputStream(fos);
ArchiveOutputStream aos = new ZipArchiveOutputStream(bos);){
Path dirPath = Paths.get(sourceFile);
Files.walkFileTree(dirPath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
ArchiveEntry entry = new ZipArchiveEntry(dir.toFile(), dirPath.relativize(dir).toString());
aos.putArchiveEntry(entry);
aos.closeArchiveEntry();
return super.preVisitDirectory(dir, attrs);
}
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
ArchiveEntry entry = new ZipArchiveEntry(
file.toFile(), dirPath.relativize(file).toString());
aos.putArchiveEntry(entry);
IOUtils.copy(new FileInputStream(file.toFile()), aos);
aos.closeArchiveEntry();
return super.visitFile(file, attrs);
}
});
} catch (IOException e) {
System.out.println("压缩失败,原因:" + e.getMessage());
}
System.out.println("压缩完毕,耗时:" + (System.currentTimeMillis() - d1) + " ms");
}
}
## 测试类
@Slf4j
public class SftpTest {
@Test
public void uploadTest() throws IOException {
SftpUtils sftpUtils = new SftpUtils("IP", "port", "username", "password", "UTF-8");
try {
sftpUtils.setReady();
// 本地目录
String localPath = ("D:"+ File.separator + "game" + File.separator);
// 文件名称
String fileName = "植物大战僵尸";
// 服务器目录
// String sftpPath = ("File.separator" + "opt" + "File.separator" + "pvz" + "File.separator ");
String sftpPath = ("/" + "opt" + "/" + "pvz" + "/");
// 文件格式
String suffix = ".zip";
String localFilePath = localPath + fileName + suffix;
String sftpFilePath = sftpPath + fileName + suffix;
String localFolder = localPath + fileName;
log.info("local:" + localFilePath);
log.info("sftp:" + sftpFilePath);
// 本地文件
File file = new File(localFilePath);
File fileFolder = new File(localFolder);
// 文件不存在则压缩文件
if (file.exists()){
boolean deleteFlag = file.delete();
if (deleteFlag){
log.info("删除成功!");
}else {
throw new Exception("删除失败!");
}
}
// 文件夹存在则压缩文件夹
if (fileFolder.exists()){
ZipUtil.compress(localFolder , localFilePath);
}else {
throw new Exception("文件夹不存在,请确认!");
}
// 设置编码格式
sftpUtils.setEncoding();
// 判断服务器是否需要创建文件夹
if (sftpUtils.isDirExist(sftpPath,sftpUtils.sftp)){
sftpUtils.sftp.cd(sftpPath);
}else {
sftpUtils.createFolder(sftpPath);
}
// 删除服务器上的旧文件
sftpUtils.delete(sftpPath,fileName,sftpUtils.sftp);
// 展示文件
List<String> fileList1 = sftpUtils.listFiles(sftpPath);
log.info("上传前目录列表:");
fileList1.forEach(System.out::println);
// System.out.println("上传前服务器文件:");
// for (String f:fileList1){
// System.out.println(f);
// }
// 上传
boolean result = sftpUtils.uploadFile(localFilePath,fileName + suffix,file);
// 展示文件
List<String> fileList2 = sftpUtils.listFiles(sftpPath);
System.out.println("上传后目录列表:");
fileList2.forEach(System.out::println);
// for (String f:fileList2){
// System.out.println(f);
// }
if (result){
log.info("上传成功!");
}else {
log.info("上传失败!");
}
}catch (Exception e){
log.error(e.getMessage());
}finally {
sftpUtils.close();
}
}
}