基于Spring+Angular5通过SFTP连接远程机器并获取文件目录咨询
Got it, let's walk through this step by step since you’re already able to access the remote machine via WinSCP over SFTP, and need to integrate this into your Spring + Angular5 stack to fetch file/directory lists. Here's how to pull it off:
We’ll use JSch—the most widely used Java library for SFTP—to handle the remote connection and file listing.
Step 1: Add JSch Dependency
First, include the JSch library in your pom.xml (Maven) or build.gradle (Gradle):
Maven:
<dependency> <groupId>com.jcraft</groupId> <artifactId>jsch</artifactId> <version>0.1.55</version> <!-- Use the latest stable version --> </dependency>
Gradle:
implementation 'com.jcraft:jsch:0.1.55'
Step 2: Create an SFTP Utility Class
This class will handle connecting to the remote server, fetching file lists, and cleaning up connections. We’ll externalize credentials to avoid hardcoding (use application.properties):
import com.jcraft.jsch.*; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import java.util.ArrayList; import java.util.List; import java.util.Properties; @Component public class SftpClient { private Session session; private ChannelSftp channelSftp; @Value("${sftp.host}") private String sftpHost; @Value("${sftp.port}") private int sftpPort; @Value("${sftp.username}") private String sftpUsername; @Value("${sftp.password}") private String sftpPassword; // Establish SFTP connection public void connect() throws JSchException { JSch jsch = new JSch(); session = jsch.getSession(sftpUsername, sftpHost, sftpPort); session.setPassword(sftpPassword); // Disable strict host checking for dev (use known_hosts file in production!) Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); session.setConfig(config); session.connect(); channelSftp = (ChannelSftp) session.openChannel("sftp"); channelSftp.connect(); } // Fetch file/directory list from the specified root path public List<String> getFileList(String rootPath) throws SftpException { List<String> fileList = new ArrayList<>(); if (!channelSftp.isConnected()) { throw new SftpException(ChannelSftp.SSH_FX_FAILURE, "SFTP connection not established"); } // List all entries, skip "." and ".." @SuppressWarnings("unchecked") java.util.Vector<ChannelSftp.LsEntry> entries = channelSftp.ls(rootPath); for (ChannelSftp.LsEntry entry : entries) { String filename = entry.getFilename(); if (!filename.equals(".") && !filename.equals("..")) { fileList.add(filename); } } return fileList; } // Clean up connection resources public void disconnect() { if (channelSftp != null && channelSftp.isConnected()) { channelSftp.disconnect(); } if (session != null && session.isConnected()) { session.disconnect(); } } }
Step 3: Add SFTP Credentials to application.properties
# SFTP Configuration sftp.host=your-remote-machine-ip-or-hostname sftp.port=22 sftp.username=your-sftp-username sftp.password=your-sftp-password
Step 4: Create a REST Controller for Frontend Access
Expose an API endpoint that your Angular app can call to fetch the file list:
import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.util.List; @RestController public class SftpFileController { private final SftpClient sftpClient; public SftpFileController(SftpClient sftpClient) { this.sftpClient = sftpClient; } @GetMapping("/api/sftp/files") public ResponseEntity<?> getSftpFiles(@RequestParam String rootPath) { try { sftpClient.connect(); List<String> fileList = sftpClient.getFileList(rootPath); sftpClient.disconnect(); return new ResponseEntity<>(fileList, HttpStatus.OK); } catch (Exception e) { return new ResponseEntity<>("Failed to fetch files: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR); } } }
Optional: Private Key Authentication
If you use SSH keys instead of passwords, replace the password setup in connect() with:
// Path to your private key file (e.g., "C:/Users/YourUser/.ssh/id_rsa") jsch.addIdentity("path-to-your-private-key");
We’ll create a service to call the Spring API and a component to display the file list.
Step 1: Create an SFTP Service
Generate a service to handle HTTP requests to the backend:
import { Injectable } from '@angular/core'; import { HttpClient } from '@angular/common/http'; import { Observable } from 'rxjs'; @Injectable() export class SftpService { private apiUrl = 'http://your-spring-backend-url/api/sftp/files'; constructor(private http: HttpClient) { } getFileList(rootPath: string): Observable<string[]> { return this.http.get<string[]>(`${this.apiUrl}?rootPath=${encodeURIComponent(rootPath)}`); } }
Step 2: Create a File List Component
Generate a component to let users input the root path and display results:
Component TypeScript (file-list.component.ts):
import { Component } from '@angular/core'; import { SftpService } from './sftp.service'; @Component({ selector: 'app-file-list', templateUrl: './file-list.component.html' }) export class FileListComponent { fileList: string[] = []; rootPath: string = '/your-default-root-path'; // e.g., "/home/user/docs" errorMessage: string = ''; constructor(private sftpService: SftpService) { } fetchFiles() { this.sftpService.getFileList(this.rootPath).subscribe( files => { this.fileList = files; this.errorMessage = ''; }, error => { this.errorMessage = error.error; this.fileList = []; } ); } }
Component HTML (file-list.component.html):
<div class="sftp-container"> <input type="text" [(ngModel)]="rootPath" placeholder="Enter remote root path" class="path-input" > <button (click)="fetchFiles()" class="fetch-btn">Fetch Files</button> </div> <div *ngIf="errorMessage" class="error-alert"> {{ errorMessage }} </div> <ul *ngIf="fileList.length > 0" class="file-list"> <li *ngFor="let file of fileList" class="file-item"> {{ file }} </li> </ul> <p *ngIf="fileList.length === 0 && !errorMessage" class="empty-message"> No files or directories found in this path. </p>
Step 3: Fix CORS Issues
If your Angular app runs on a different port than Spring, add a CORS configuration to your Spring backend:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.servlet.config.annotation.CorsRegistry; import org.springframework.web.servlet.config.annotation.WebMvcConfigurer; @Configuration public class CorsConfig { @Bean public WebMvcConfigurer corsConfigurer() { return new WebMvcConfigurer() { @Override public void addCorsMappings(CorsRegistry registry) { registry.addMapping("/api/**") .allowedOrigins("http://your-angular-app-url:4200") // Your Angular app's URL .allowedMethods("GET") .allowedHeaders("*"); } }; } }
- Security: In production, never hardcode credentials. Use environment variables, a secrets manager, or encrypted property files. Re-enable strict host key checking with a
known_hostsfile. - Error Handling: Add granular error handling (e.g., handle connection timeouts, permission denied errors) and user-friendly messages.
- Performance: For large directories, implement pagination or lazy loading to avoid fetching all entries at once.
- Connection Management: Use an SFTP connection pool instead of creating a new connection per request for better efficiency.
内容的提问来源于stack exchange,提问作者Jeizi

