package com.smartor.common; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.JSch; import com.jcraft.jsch.Session; import lombok.extern.slf4j.Slf4j; import org.junit.Test; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.io.File; import java.io.FileOutputStream; import java.util.Vector; @Slf4j @Component public class FtpService { @Value("${FTP_SERVER}") private String FTP_SERVER; @Value("${FTP_USERNAME}") private String FTP_USERNAME; @Value("${FTP_PASSWORD}") private String FTP_PASSWORD; public void downloadFolder(String remoteDir, String localDir) { Session session = null; ChannelSftp channelSftp = null; try { // 1. 创建 JSch 实例并设置会话 JSch jsch = new JSch(); session = jsch.getSession(FTP_USERNAME, FTP_SERVER, 8094); session.setPassword(FTP_PASSWORD); // 跳过主机密钥检查 session.setConfig("StrictHostKeyChecking", "no"); // 2. 连接到 SFTP 服务器 session.connect(); channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); // 3. 开始递归下载 downloadDirectory(channelSftp, remoteDir, localDir); } catch (Exception e) { e.printStackTrace(); } finally { // 4. 关闭连接 if (channelSftp != null) { channelSftp.disconnect(); } if (session != null) { session.disconnect(); } } } /** * 递归下载远程目录到本地 * * @param channelSftp SFTP 通道 * @param remoteDir 远程目录路径 * @param localDir 本地目录路径 * @throws Exception 异常 */ private static void downloadDirectory(ChannelSftp channelSftp, String remoteDir, String localDir) throws Exception { // 确保本地目录存在 File localDirectory = new File(localDir); if (!localDirectory.exists()) { localDirectory.mkdirs(); } // 列出远程目录中的所有文件和文件夹 Vector entries = channelSftp.ls(remoteDir); for (ChannelSftp.LsEntry entry : entries) { String fileName = entry.getFilename(); // 跳过 "." 和 ".." if (".".equals(fileName) || "..".equals(fileName)) { continue; } String remoteFilePath = remoteDir + "/" + fileName; String localFilePath = localDir + File.separator + fileName; if (entry.getAttrs().isDir()) { // 如果是文件夹,递归下载 downloadDirectory(channelSftp, remoteFilePath, localFilePath); } else { // 如果是文件,覆盖下载 File localFile = new File(localFilePath); // 如果本地文件已存在,先删除 if (localFile.exists()) { localFile.delete(); } try (FileOutputStream fos = new FileOutputStream(localFile)) { channelSftp.get(remoteFilePath, fos); log.error("文件下载成功:{}", remoteFilePath); } catch (Exception e) { System.err.println("文件下载失败: " + remoteFilePath); e.printStackTrace(); } } } } // // @Test // public void aa() { // downloadFolder("/", "D:\\ruoyi\\uploadPath\\upload\\vadio\\voice"); // } }