1. SFTP 简介
SFTP(SSH File Transfer Protocol,也称 Secret File Transfer Protocol),是一种基于SSH(安全外壳)的安全的文件传输协议。使用SFTP协议可以在文件传输过程中提供一种安全的加密算法,从而保证数据的安全传输,所以SFTP是非常安全的。
但是,由于这种传输方式使用了加密/解密技术,所以传输效率比普通的FTP要低。SFTP是SSH的一部分,SFTP没有单独的守护进程,它必须使用SSHD守护进程(默认端口22)来完成相应的连接操作,sftp服务作为SSH的一个子服务,是通过/etc/ssh/sshd_config配置文件中的Subsystem实现的,如果没有配置Subsystem参数,则系统是不能进行sftp访问的。所以,要分离SSH和sftp服务的画,基本思路就是创建两个SSHD进程,分别监听不同的端口,一个作为SSH服务的deamon,另一个作为sftp服务的deamon.
1.1 Spring Integration核心组件
- SftpSessionFactory: sftp客户端与服务端的会话工厂,客户端每次访问服务器时都会创建一个session对象,且可以通过SftpSessionCaching 将session对象缓存起来,支持session共享,即可以在一个会话上进行多个channel的操作。如果session被充值,则在最后一次channel关闭之后,将断开连接。- isSharedSession为true时session将共享。
- SftpSessionCaching: sftp会话缓存工厂。通过poolSize和sessionWaiteTimeout来设置缓缓池的大小和会话等待超市时间。缓存池默认是无限大,超市事件默认是Integer.MAX_VALUE。
- SftpRemoteFileTemplate: 基于- SftpSessionFactory创建的sftp文件操作模板类,其父类时- RemoteFileTemplate。支持上传、下载、追加、删除、重命名、列表、是否存在等。基于输入输出流实现。
- SftpInboundChannelAdapter: sftp 入站通道适配器。可同步远程目录到本地,且可监听远程文件的操作,可实现下载
- SftpOutboundChannelAdapter:sftp 出站通道适配器。实际是一个 sftp 消息处理器,将在服务器与客户端之间创建一个消息传输通道。此处的消息指的是 Message 的 payload,其支持 File、byte[]、String。其支持 ls、nlst、get、rm、mget、mv、put、mput 操作
- Channel Adapter: 通道适配器,实际上是适配消息在客户端和服务器之间的传输。inbound adapter 是接收其它系统的消息,outbound adapter 是发送消息到其它系统
- @ServiceActivator: 将注解作用的方法注册为处理消息的站点,inputChannel 表示接收消息的通道
2. 环境搭建
docker run -p 22:22 -d atmoz/sftp foo:pass:::upload

3. 代码工程
实现文件上传和下载
- pom.xml 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 <project xmlns="http://maven.apache.org/POM/4.0.0"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
 <parent>
 <artifactId>springboot-demo</artifactId>
 <groupId>com.ygb</groupId>
 <version>1.0-SNAPSHOT</version>
 </parent>
 <modelVersion>4.0.0</modelVersion>
 <artifactId>sftp</artifactId>
 <properties>
 <maven.compiler.source>8</maven.compiler.source>
 <maven.compiler.target>8</maven.compiler.target>
 </properties>
 <dependencies>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-web</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-autoconfigure</artifactId>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-starter-test</artifactId>
 <scope>test</scope>
 </dependency>
 <dependency>
 <groupId>org.springframework.integration</groupId>
 <artifactId>spring-integration-sftp</artifactId>
 <!-- <version>5.4.1</version>-->
 <version>5.2.8.RELEASE</version>
 </dependency>
 <dependency>
 <groupId>org.springframework.boot</groupId>
 <artifactId>spring-boot-configuration-processor</artifactId>
 <optional>true</optional>
 </dependency>
 <dependency>
 <groupId>org.projectlombok</groupId>
 <artifactId>lombok</artifactId>
 <optional>true</optional>
 </dependency>
 </dependencies>
 </project>
- service 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246
 247
 248
 249
 250
 251
 252
 253
 254
 255
 256
 257
 258
 259
 260
 261
 262
 263
 264
 265
 266
 267
 268
 269
 270
 271
 272
 273
 274
 275
 276
 277
 278
 279
 280
 281
 282
 283
 284
 285
 286
 287
 288
 289
 290
 291
 292
 293
 294
 295
 296
 297
 298
 299
 300
 301
 302
 303
 304
 305
 306
 307
 308
 309
 310
 311
 312
 313
 314
 315
 316
 317
 318
 319
 320
 321
 322
 323
 324
 325
 326import com.et.sftp.config.SftpConfiguration; 
 import com.et.sftp.service.SftpService;
 import lombok.extern.slf4j.Slf4j;
 import org.springframework.integration.file.remote.FileInfo;
 import org.springframework.integration.sftp.session.SftpRemoteFileTemplate;
 import org.springframework.stereotype.Component;
 import org.springframework.web.multipart.MultipartFile;
 import javax.annotation.Resource;
 import java.io.*;
 import java.util.List;
 public class SftpServiceImpl implements SftpService {
 
 private SftpRemoteFileTemplate remoteFileTemplate;
 
 private SftpConfiguration.SftpGateway gateway;
 /**
 * single file upload
 *
 * @param file File
 */
 
 public void uploadFile(File file) {
 gateway.upload(file);
 }
 /**
 * single file upload by byte[]
 *
 * @param bytes bytes
 */
 
 public void uploadFile(byte[] bytes, String name) {
 try {
 gateway.upload(bytes, name);
 } catch (Exception e) {
 log.error("error:", e);
 }
 }
 /**
 * uopload by path
 *
 * @param bytes
 * @param filename
 * @param path
 */
 
 public void upload(byte[] bytes, String filename, String path) {
 try {
 gateway.upload(bytes, filename, path);
 } catch (Exception e) {
 log.error("error:", e);
 }
 }
 /**
 * list files by path
 *
 * @param path
 * @return List<String>
 */
 
 public String[] listFile(String path) {
 try {
 return remoteFileTemplate.execute(session -> {
 return session.listNames(path);
 });
 } catch (Exception e) {
 log.error("error:", e);
 }
 return null;
 }
 /**
 * list file and directory by path
 *
 * @param path
 * @return List<String>
 */
 
 public List<FileInfo> listALLFile(String path) {
 return gateway.listFile(path);
 }
 /**
 * download
 *
 * @param fileName
 * @param savePath
 * @return File
 */
 
 public File downloadFile(String fileName, String savePath) {
 try {
 return remoteFileTemplate.execute(session -> {
 remoteFileTemplate.setAutoCreateDirectory(true);
 boolean existFile = session.exists(fileName);
 if (existFile) {
 InputStream is = session.readRaw(fileName);
 return convertInputStreamToFile(is, savePath);
 } else {
 return null;
 }
 });
 } catch (Exception e) {
 log.error("error:", e);
 }
 return null;
 }
 /**
 * read file
 *
 * @param fileName
 * @return InputStream
 */
 
 public InputStream readFile(String fileName) {
 return remoteFileTemplate.execute(session -> {
 return session.readRaw(fileName);
 });
 }
 /**
 * files is exists
 *
 * @param filePath
 * @return boolean
 */
 
 public boolean existFile(String filePath) {
 try {
 return remoteFileTemplate.execute(session ->
 session.exists(filePath));
 } catch (Exception e) {
 log.error("error:", e);
 }
 return false;
 }
 public void renameFile(String file1, String file2) {
 try {
 remoteFileTemplate.execute(session -> {
 session.rename(file1, file2);
 return true;
 });
 } catch (Exception e) {
 log.error("error:", e);
 }
 }
 /**
 * create directory
 *
 * @param dirName
 * @return
 */
 
 public boolean mkdir(String dirName) {
 return remoteFileTemplate.execute(session -> {
 if (!existFile(dirName)) {
 return session.mkdir(dirName);
 } else {
 return false;
 }
 });
 }
 /**
 * delete file
 *
 * @param fileName
 * @return boolean
 */
 
 public boolean deleteFile(String fileName) {
 return remoteFileTemplate.execute(session -> {
 boolean existFile = session.exists(fileName);
 if (existFile) {
 return session.remove(fileName);
 } else {
 log.info("file : {} not exist", fileName);
 return false;
 }
 });
 }
 /**
 * batch upload (MultipartFile)
 *
 * @param files List<MultipartFile>
 * @throws IOException
 */
 
 public void uploadFiles(List<MultipartFile> files, boolean deleteSource) throws IOException {
 try {
 for (MultipartFile multipartFile : files) {
 if (multipartFile.isEmpty()) {
 continue;
 }
 File file = convert(multipartFile);
 gateway.upload(file);
 if (deleteSource) {
 file.delete();
 }
 }
 } catch (Exception e) {
 log.error("error:", e);
 }
 }
 /**
 * batch upload (MultipartFile)
 *
 * @param files List<MultipartFile>
 * @throws IOException
 */
 
 public void uploadFiles(List<MultipartFile> files) throws IOException {
 uploadFiles(files, true);
 }
 /**
 * single file upload (MultipartFile)
 *
 * @param multipartFile MultipartFile
 * @throws IOException
 */
 
 public void uploadFile(MultipartFile multipartFile) throws IOException {
 gateway.upload(convert(multipartFile));
 }
 
 public String listFileNames(String dir) {
 return gateway.nlstFile(dir);
 }
 
 public File getFile(String dir) {
 return null;
 }
 
 public List<File> mgetFile(String dir) {
 return null;
 }
 
 public boolean rmFile(String file) {
 return false;
 }
 
 public boolean mv(String sourceFile, String targetFile) {
 return false;
 }
 
 public File putFile(String dir) {
 return null;
 }
 
 public List<File> mputFile(String dir) {
 return null;
 }
 
 public String nlstFile(String dir) {
 return gateway.nlstFile(dir);
 }
 private static File convertInputStreamToFile(InputStream inputStream, String savePath) {
 OutputStream outputStream = null;
 File file = new File(savePath);
 try {
 outputStream = new FileOutputStream(file);
 int read;
 byte[] bytes = new byte[1024];
 while ((read = inputStream.read(bytes)) != -1) {
 outputStream.write(bytes, 0, read);
 }
 log.info("convert InputStream to file done, savePath is : {}", savePath);
 } catch (IOException e) {
 log.error("error:", e);
 } finally {
 if (inputStream != null) {
 try {
 inputStream.close();
 } catch (IOException e) {
 e.printStackTrace();
 }
 }
 if (outputStream != null) {
 try {
 outputStream.close();
 } catch (IOException e) {
 log.error("error:", e);
 }
 }
 }
 return file;
 }
 private static File convert(MultipartFile file) throws IOException {
 File convertFile = new File(file.getOriginalFilename());
 convertFile.createNewFile();
 FileOutputStream fos = new FileOutputStream(convertFile);
 fos.write(file.getBytes());
 fos.close();
 return convertFile;
 }
 }
- SftpService接口 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79import org.springframework.integration.file.remote.FileInfo; 
 import org.springframework.web.multipart.MultipartFile;
 import java.io.File;
 import java.io.IOException;
 import java.io.InputStream;
 import java.util.List;
 public interface SftpService {
 void uploadFile(File file);
 void uploadFile(byte[] bytes, String name);
 
 void upload(byte[] bytes, String filename, String path);
 
 String[] listFile(String path);
 List<FileInfo> listALLFile(String path);
 
 File downloadFile(String fileName, String savePath);
 InputStream readFile(String fileName);
 
 boolean existFile(String filePath);
 boolean mkdir(String dirName);
 boolean deleteFile(String fileName);
 
 void uploadFiles(List<MultipartFile> files, boolean deleteSource) throws IOException;
 
 void uploadFiles(List<MultipartFile> files) throws IOException;
 
 void uploadFile(MultipartFile multipartFile) throws IOException;
 
 String listFileNames(String dir);
 File getFile(String dir);
 
 List<File> mgetFile(String dir);
 
 boolean rmFile(String file);
 
 boolean mv(String sourceFile, String targetFile);
 
 File putFile(String dir);
 
 List<File> mputFile(String dir);
 //void upload(File file);
 //void upload(byte[] inputStream, String name);
 //List<File> downloadFiles(String dir);
 String nlstFile(String dir);
 }
- 配置config - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
 100
 101
 102
 103
 104
 105
 106
 107
 108
 109
 110
 111
 112
 113
 114
 115
 116
 117
 118
 119
 120
 121
 122
 123
 124
 125
 126
 127
 128
 129
 130
 131
 132
 133
 134
 135
 136
 137
 138
 139
 140
 141
 142
 143
 144
 145
 146
 147
 148
 149
 150
 151
 152
 153
 154
 155
 156
 157
 158
 159
 160
 161
 162
 163
 164
 165
 166
 167
 168
 169
 170
 171
 172
 173
 174
 175
 176
 177
 178
 179
 180
 181
 182
 183
 184
 185
 186
 187
 188
 189
 190
 191
 192
 193
 194
 195
 196
 197
 198
 199
 200
 201
 202
 203
 204
 205
 206
 207
 208
 209
 210
 211
 212
 213
 214
 215
 216
 217
 218
 219
 220
 221
 222
 223
 224
 225
 226
 227
 228
 229
 230
 231
 232
 233
 234
 235
 236
 237
 238
 239
 240
 241
 242
 243
 244
 245
 246- import com.jcraft.jsch.ChannelSftp; 
 import org.springframework.beans.factory.BeanFactory;
 import org.springframework.boot.context.properties.EnableConfigurationProperties;
 import org.springframework.context.annotation.Bean;
 import org.springframework.context.annotation.Configuration;
 import org.springframework.expression.common.LiteralExpression;
 import org.springframework.expression.spel.standard.SpelExpressionParser;
 import org.springframework.integration.annotation.Gateway;
 import org.springframework.integration.annotation.MessagingGateway;
 import org.springframework.integration.annotation.ServiceActivator;
 import org.springframework.integration.core.MessagingTemplate;
 import org.springframework.integration.file.FileNameGenerator;
 import org.springframework.integration.file.remote.FileInfo;
 import org.springframework.integration.file.remote.session.CachingSessionFactory;
 import org.springframework.integration.file.remote.session.SessionFactory;
 import org.springframework.integration.file.support.FileExistsMode;
 import org.springframework.integration.sftp.gateway.SftpOutboundGateway;
 import org.springframework.integration.sftp.outbound.SftpMessageHandler;
 import org.springframework.integration.sftp.session.DefaultSftpSessionFactory;
 import org.springframework.integration.sftp.session.SftpRemoteFileTemplate;
 import org.springframework.messaging.Message;
 import org.springframework.messaging.MessageHandler;
 import org.springframework.messaging.handler.annotation.Header;
 import org.springframework.messaging.handler.annotation.Payload;
 import javax.annotation.Resource;
 import java.io.File;
 import java.util.List;
 public class SftpConfiguration {
 
 private SftpProperties properties;
 
 public MessagingTemplate messagingTemplate(BeanFactory beanFactory) {
 MessagingTemplate messagingTemplate = new MessagingTemplate();
 messagingTemplate.setBeanFactory(beanFactory);
 return messagingTemplate;
 }
 
 public SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory() {
 DefaultSftpSessionFactory factory = new DefaultSftpSessionFactory(true);
 factory.setHost(properties.getHost());
 factory.setPort(properties.getPort());
 factory.setUser(properties.getUsername());
 factory.setPassword(properties.getPassword());
 factory.setAllowUnknownKeys(true);
 // factory.setTestSession(true);
 // return factory;
 return new CachingSessionFactory<ChannelSftp.LsEntry>(factory);
 }
 
 public SftpRemoteFileTemplate remoteFileTemplate(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 return new SftpRemoteFileTemplate(sftpSessionFactory);
 }
 
 
 public MessageHandler downloadHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sftpSessionFactory, "mget", "payload");
 sftpOutboundGateway.setOptions("-R");
 sftpOutboundGateway.setFileExistsMode(FileExistsMode.REPLACE_IF_MODIFIED);
 sftpOutboundGateway.setLocalDirectory(new File(properties.getLocalDir()));
 sftpOutboundGateway.setAutoCreateLocalDirectory(true);
 return sftpOutboundGateway;
 }
 
 
 public MessageHandler uploadHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory);
 handler.setRemoteDirectoryExpression(new LiteralExpression(properties.getRemoteDir()));
 // handler.setChmod();
 handler.setFileNameGenerator(message -> {
 if (message.getPayload() instanceof File) {
 return ((File) message.getPayload()).getName();
 } else {
 throw new IllegalArgumentException("File expected as payload.");
 }
 });
 return handler;
 }
 
 
 public MessageHandler multiTypeHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory);
 handler.setRemoteDirectoryExpression(new LiteralExpression(properties.getRemoteDir()));
 handler.setFileNameGenerator(message -> {
 if (message.getPayload() instanceof byte[]) {
 return (String) message.getHeaders().get("name");
 } else {
 throw new IllegalArgumentException("byte[] expected as payload.");
 }
 });
 return handler;
 }
 
 
 public MessageHandler lsHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sftpSessionFactory, "ls", "payload");
 sftpOutboundGateway.setOptions("-R");
 return sftpOutboundGateway;
 }
 
 
 public MessageHandler listFileNamesHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sftpSessionFactory, "nlst", "payload");
 return sftpOutboundGateway;
 }
 
 
 public MessageHandler getFileHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpOutboundGateway sftpOutboundGateway = new SftpOutboundGateway(sftpSessionFactory, "get", "payload");
 sftpOutboundGateway.setOptions("-R");
 sftpOutboundGateway.setFileExistsMode(FileExistsMode.REPLACE_IF_MODIFIED);
 sftpOutboundGateway.setLocalDirectory(new File(properties.getLocalDir()));
 sftpOutboundGateway.setAutoCreateLocalDirectory(true);
 return sftpOutboundGateway;
 }
 /**
 * create by: qiushicai
 * create time: 2020/11/20
 *
 * @return
 */
 
 
 public MessageHandler abcHandler(SessionFactory<ChannelSftp.LsEntry> sftpSessionFactory) {
 SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory);
 handler.setRemoteDirectoryExpression(new LiteralExpression(properties.getRemoteDir()));
 handler.setFileNameGenerator(message -> {
 if (message.getPayload() instanceof byte[]) {
 System.out.println("receive message:" + new String((byte[]) message.getPayload()));
 message.getHeaders().forEach((k, v) -> System.out.println("\t\t|---" + k + "=" + v));
 return "ok";
 } else {
 throw new IllegalArgumentException("byte[] expected as payload.");
 }
 });
 return handler;
 }
 /**
 *
 * the #root object is the Message, which has two properties (headers and payload) that allow such expressions as payload, payload.thing, headers['my.header'], and so on
 *
 * link{ https://stackoverflow.com/questions/46650004/spring-integration-ftp-create-dynamic-directory-with-remote-directory-expressi}
 * link{ https://docs.spring.io/spring-integration/reference/html/spel.html}
 * @return
 */
 
 
 public MessageHandler pathHandler() {
 SftpMessageHandler handler = new SftpMessageHandler(sftpSessionFactory());
 // automatically create the remote directory
 handler.setAutoCreateDirectory(true);
 handler.setRemoteDirectoryExpression(new SpelExpressionParser().parseExpression("headers[path]"));
 handler.setFileNameGenerator(new FileNameGenerator() {
 
 public String generateFileName(Message<?> message) {
 return (String) message.getHeaders().get("filename");
 }
 });
 return handler;
 }
 /**
 * <ul>
 * <li>ls (list files)
 * <li> nlst (list file names)
 * <li> get (retrieve a file)
 * <li> mget (retrieve multiple files)
 * <li> rm (remove file(s))
 * <li> mv (move and rename file)
 * <li> put (send a file)
 * <li> mput (send multiple files)
 * </ul>
 *
 * @author :qiushicai
 * @date :Created in 2020/11/20
 * @description:outbound gateway API
 * @version:
 */
 
 public interface SftpGateway {
 //ls (list files)
 
 List<FileInfo> listFile(String dir);
 
 String nlstFile(String dir);
 
 File getFile(String dir);
 
 List<File> mgetFile(String dir);
 
 boolean rmFile(String file);
 
 boolean mv(String sourceFile, String targetFile);
 
 File putFile(String dir);
 
 List<File> mputFile(String dir);
 
 void upload(File file);
 
 void upload(byte[] inputStream, String name);
 
 void upload( byte[] file, String filename, String path);
 
 List<File> downloadFiles(String dir);
 }
 }
- SftpProperties - 1 
 2
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13- import lombok.Data; 
 import org.springframework.boot.context.properties.ConfigurationProperties;
 public class SftpProperties {
 private String host;
 private Integer port;
 private String password;
 private String username;
 private String remoteDir;
 private String localDir;
 }
- 配置文件 - 1 
 2
 3
 4
 5
 6
 7
 8
 ##sftp properties
 =127.0.0.1
 =22
 =foo
 =pass
 =/upload
 =D:\\tmp\\sync-files
4. 测试
- 文件是否存在 - 1 
 2
 3
 4
 5
 void testExistFile() {
 boolean existFile = sftpService.existFile("/upload/home222.js");
 System.out.println(existFile);
 }
- 列出目录下的文件 - 1 
 2
 3
 4
 void listFileTest() {
 sftpService.listALLFile("/upload").stream().forEach(System.out::println);
 }
- 下载文件 - 1 
 2
 3
 4
 void testDownLoad() throws Exception {
 sftpService.downloadFile("/upload/home.js", "D:\\tmp\\c222c.js");
 }
- 上传 - 1 
 2
 3
 4
 void uploadFile() {
 sftpService.uploadFile(new File("D:\\tmp\\cc.js"));
 }
 
         
              