编程开源技术交流,分享技术与知识

网站首页 > 开源技术 正文

使用SpringBoot从SFTP服务器下载文件

wxchong 2024-07-05 01:43:05 开源技术 14 ℃ 0 评论

在本文中,我们将创建一个 SpringBoot 服务来读取位于 SFTP 服务器上的远程文件并将文件复制到本地目录。

首先在pom.xml文件中添加以下依赖项。

<!-- https://mvnrepository.com/artifact/com.jcraft/jsch -->
<dependency>
 <groupId>com.jcraft</groupId>
 <artifactId>jsch</artifactId>
 <version>0.1.55</version>
</dependency>

创建FileHelper.java

getSession方法将返回 Session 类的对象。JSch 库的会话类用于创建 SSH 会话。通过验证用户身份,它会创建与远程 SSH 服务器的连接。SFTP 服务器的默认端口一般是22。

private Session getSession(String user, String password){
    String host = "10.0.0.10";
    String port = "22";
    JSch jsch = new JSch();
    Session session = null;
    try {
        session = jsch.getSession(user, host,Integer.valueOf(port));
        session.setPassword(password);
        session.setConfig("StrictHostKeyChecking", "no");
        session.connect();
        LOGGER.info("SFTP Session Created");
    } catch (JSchException e) {
        /* Handle session or channel disconnect exception
        This catch block will handle any exceptions related to session or channel
        disconnects that are thrown by the session.connect() or channelSftp.connect() methods */

        errorLogger.error("Could Not Create SFTP Session, Possible reasons: {}", e.getMessage());
        e.printStackTrace();
    }
    return session;
}
private ChannelSftp getChannel(Session session){
    ChannelSftp channelSftp = null;
    if (session != null && session.isConnected()){
        try {
            channelSftp = (ChannelSftp) session.openChannel("sftp");
            channelSftp.connect();
            LOGGER.info("SFTP Channel Created");
        } catch (JSchException e) {
            /* Handle SFTP related exception
            This catch block will handle any SFTP-related exceptions that may occur during SFTP
            operations like listing files (channelSftp.ls()) or changing directories (channelSftp.cd()) */

            errorLogger.error("Could Not Create SFTP Channel, Possible reasons: {}", e.getMessage());
            e.printStackTrace();
        }
    }
    return channelSftp;
}

getChannel方法将返回 ChannelSftp 类的对象。JSch 库中的 ChannelSftp 类用于使用 SFTP(SSH 文件传输协议)与远程服务器进行交互。它提供了一组方法,允许您通过安全的 SSH 连接执行各种与文件相关的操作,包括上传和下载文件、列出目录、创建目录和删除文件

private Vector<ChannelSftp.LsEntry> getFilesNamesFromSFTP(ChannelSftp channelSftp, String remoteDirectory, String filePrefixAndExtension){
    Vector<ChannelSftp.LsEntry> files = new Vector<>();
    if(channelSftp != null && channelSftp.isConnected()){
        try {
            // Change to the remote directory
            channelSftp.cd(remoteDirectory);
            // List files in the remote directory
            files = channelSftp.ls(filePrefixAndExtension);
        } catch (SftpException e) {
            errorLogger.error("Could Not Create SFTP Channel, Possible reasons: {}", e.getMessage());
            e.printStackTrace();
        }
    }
    return files;
}

getFilesNamesFromSFTP方法获取 SFTP 服务器中可用的文件名列表。我们可以使用 ChannelSftp 类的cd函数更改远程服务器的目录,其中我们可以使用ChannelSftp 类的ls函数使用前缀和扩展名过滤文件。

private String downloadFileToLocalDirFromSFTP(ChannelSftp channelSftp, String localDirectory, ChannelSftp.LsEntry file){
    if(channelSftp != null && channelSftp.isConnected()){
        try {
            String localFilePath = localDirectory + File.separator + file.getFilename();
            // Download the file from the remote directory to the local directory
            channelSftp.get(file.getFilename(), localFilePath);
            File downloadedFile = new File(localFilePath);
            Date dateModify = new Date(file.getAttrs().getMTime() * 1000L);
            downloadedFile.setLastModified(dateModify.getTime());
            LOGGER.info("File copied from SFTP, Filename: {}", downloadedFile.getName());
            return downloadedFile.getName();
        } catch (SftpException e) {
            errorLogger.error("Could Not Download File from SFTP Server, File Name: {}, Possible reasons: {}",file.getFilename(), e.getMessage());
            e.printStackTrace();
        }
    }
    return null;
}

downloadFileToLocalDirFromSFTP方法使用 ChannelSftp 类的get函数将一个特定文件复制到我们的本地目录,并返回复制的文件名。

private void disconnectChannelAndSession(ChannelSftp channelSftp,Session session){
    // Disconnect the SFTP channel and session
    if (channelSftp != null && channelSftp.isConnected()) {
        channelSftp.disconnect();
        LOGGER.info("SFTP Channel Disconnected from SFTP Server");
    }
    if (session != null && session.isConnected()) {
        session.disconnect();
        LOGGER.info("SFTP Session Ended from SFTP Server");
    }
}

disconnectChannelAndSession将断开SFTP通道并断开与远程SFTP服务器的会话。我们可以在完成从服务器移动或复制文件后调用此函数。

再创建我们的实体对象类FileHistory.java

@Entity
@Table(name = "file_history")
@NoArgsConstructor
@AllArgsConstructor
@Setter
@Getter
public class FileHistory {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    @Column(unique=true)
    private String fileName;
    private boolean isDownloaded = false;
    @Column(updatable = false)
    @Temporal(TemporalType.TIMESTAMP)
    private Date downloadedAt;

    public FileHistory(String fileName, boolean isDownloaded, Date downloadedAt) {
        this.fileName = fileName;
        this.isDownloaded = isDownloaded;
        this.downloadedAt = downloadedAt;
    }
}

最后创建一个SftpFileService.java类,实现我们的最终的需求。

@Service
public class SftpFileService{
  @Value("${USERNAME}")
  private String pdfSFTPUser;

  @Value("${PASSWORD}")
  private String pdfSFTPPassword;

  @Value("${REMOTE_DIR}")
  private String remoteDirectory;

  @Value("${pdf.file.dir}")
  private String localPDFDirectory;

  
  @Autowired
  private FileHelper fileHelper;

  public void copySftpPdfFiles(){

    List<FileHistory> pdfFileList = new ArrayList<FileHistory>();
    
    Session session = this.fileHelper.getSession(pdfSFTPUser, pdfSFTPPassword);
    ChannelSftp channel = this.fileHelper.getChannel(session);
    Vector<ChannelSftp.LsEntry> files = this.fileHelper.getFilesNamesFromSFTP(channel, remoteDirectory, "*.pdf");
    if(files == null || files.isEmpty()){
        return;
    }
    for (ChannelSftp.LsEntry file : files) {
        if (file == null || file.getAttrs().isDir() || file.getAttrs().getSize() <= 0 || !this.fileHistoryService.isNewFile(file.getFilename())) {
            continue;
        }
        String downloadedFileName = this.fileHelper.downloadFileToLocalDirFromSFTP(channel, localPDFDirectory, file);
        // ** when copy complete, add the name to list
        if(downloadedFileName == null){
            continue;
        }
        FileHistory pdfFile = new FileHistory(downloadedFileName,true, new Date());
        pdfFileList.add(pdfFile);
    }
    this.fileHelper.disconnectChannelAndSession(channel,session);
    // ** Add list of newly copied files ** //
    LOGGER.info("Number of New PDF Files Copied From SFTP: {}",pdfFileList.size());
 
  }
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表