1.引入pom文件依赖
com.jcraft
jsch
0.1.54
1.1 pom文件详情
4.0.0
org.springframework.boot
spring-boot-starter-parent
2.0.3.RELEASE
com.xuewei.study
study_sftp_demo
1.0
org.springframework.boot
spring-boot-starter-web
2.0.3.RELEASE
org.springframework.boot
spring-boot-starter
com.jcraft
jsch
0.1.54
org.apache.commons
commons-lang3
commons-io
commons-io
2.4
org.projectlombok
lombok
1.18.12
provided
2. 新建application.yml文件
注意:
username :登录远程服务的用户名称
password:登录远程服务的密码
host:远程服务的地址
port:连接远程服务的端口
server:
port: 9001
spring:
application:
name: study_sftp_service
servlet:
multipart:
# 单个文件的大小不能超过该值
max-file-size: 100MB
# 单个请求最大的大小不能超过该值
max-request-size: 1000MB
# 这里也可以直接作为成员变量写死在类里。这里的配置都是我自定义的,叫什么都可以。
remoteserver:
username: root
password: test001
host: 10.45.156.200
port: 22
3.项目目录结构预览
4. 编写主启动类
package com.xuewei.study;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
/**
* @Author: xuewei
* @Date: 2022/3/17 16:36
*/
@SpringBootApplication(scanBasePackages = { "com.xuewei" })
public class SftpMain {
public static void main(String[] args) {
SpringApplication.run(SftpMain.class,args);
}
}
5.编写配置类
注意:JSch登录sftp会进行Kerberos username 身份验证提示
如果需要跳过,需要添加配置如下:
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
package com.xuewei.study.config;
import com.jcraft.jsch.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* Sftp配置
* @Author: xuewei
* @Date: 2022/3/17 16:41
*/
@Configuration
@Slf4j
public class SftpConnectConfig {
/**
* FTP 登录用户名
*/
@Value("${remoteserver.username}")
private String username;
/**
* FTP 登录密码
*/
@Value("${remoteserver.password}")
private String password;
/**
* FTP 服务器地址IP地址
*/
@Value("${remoteserver.host}")
private String host;
/**
* FTP 端口
*/
@Value("${remoteserver.port}")
private String strPort;
private Session getSession() throws JSchException {
JSch jsch = new JSch();
int port = Integer.parseInt(strPort.trim());
Session session = jsch.getSession(username, host, port);
if (password != null) {
session.setPassword(password);
}
Properties config = new Properties();
config.put("StrictHostKeyChecking", "no");
// JSch登录sftp,跳过 Kerberos username 身份验证提示
config.put("PreferredAuthentications","publickey,keyboard-interactive,password");
session.setConfig(config);
session.connect();
return session;
}
/**
* 连接sftp服务器,返回的是sftp连接通道,用来操纵文件
* @throws Exception
*/
@Bean
public ChannelSftp channelSftp() {
ChannelSftp sftp = null;
try {
Session session = getSession();
Channel channel = session.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
} catch (JSchException e) {
log.error("连接失败",e);
}
return sftp;
}
/**
* 连接sftp服务器,返回exec连接通道,可以远程执行命令
* @throws Exception
*/
@Bean
public ChannelExec channelExec(){
ChannelExec sftp = null;
try {
Session session = getSession();
Channel channel = null;
channel = session.openChannel("exec");
channel.connect();
sftp = (ChannelExec) channel;
} catch (JSchException e) {
log.error("连接失败",e);
System.out.println("连接失败");
}
return sftp;
}
}
6.编写控制器
package com.xuewei.study.controller;
import com.xuewei.study.service.FileService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletResponse;
import java.io.OutputStream;
/**
* @Author: xuewei
* @Date: 2022/3/17 16:55
*/
@RestController
@Slf4j
public class FileController {
@Autowired
private FileService fileService;
@GetMapping("/download")
public void download(@RequestParam(required = true) String file, @RequestParam(required = true)String path,
HttpServletResponse response){
//设置响应信息
response.setContentType("application/octet-stream");
// filename为文件下载后保存的文件名,可自行设置,但是注意文件名后缀,要和原来的保持一致
response.setHeader("Content-Disposition", "attachment; filename=" + file);
OutputStream out = null;
try {
out = response.getOutputStream();
// 输出到客户端
out.write(fileService.download(path, file));
} catch (Exception e) {
log.error("",e);
}
}
/**
* 上传文件到服务器
* @param file 要上传到服务器的文件,注意此处的path必须在结尾添加 /
* @param path 上传到服务器的路径
*/
@PostMapping("/upload")
public void upload(@RequestBody(required = true) MultipartFile file, @RequestParam(required = true) String path){
try {
fileService.upload(file, path);
} catch (Exception e) {
log.error("",e);
}
}
}
7.编写业务类
package com.xuewei.study.service;
import com.jcraft.jsch.ChannelSftp;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.util.UUID;
/**
* @Author: xuewei
* @Date: 2022/3/17 16:43
*/
@Service
@Slf4j
public class FileService {
@Resource
private ChannelSftp channelSftp;
/**
* 从服务器获取文件并返回字节数组
* @param path 要下载文件的路径
* @param file 要下载的文件
*/
public byte[] download(String path, String file) throws Exception {
// 切换到文件所在目录
channelSftp.cd(path);
//获取文件并返回给输入流,若文件不存在该方法会抛出常
InputStream is = channelSftp.get(file);
byte[] fileData = IOUtils.toByteArray(is);
if(is != null){
is.close();
}
return fileData;
}
/**
* 将输入流的数据上传到sftp作为文件
*
* @param path
* 上传到该目录
* @param uploadFile
* 服务器保存的文件
* @throws Exception
*/
public void upload(MultipartFile uploadFile, String path) throws Exception{
String fileName = uploadFile.getOriginalFilename();
// 用uuid + 原来的文件名生成新名字,防止文件名重复也可以辨识上传的文件是哪个,可以省略这一步
String newName = UUID.randomUUID().toString().replaceAll("-","") + fileName;
File file = new File(path + newName);
//将MultipartFilez转换为File,会生成文件
FileUtils.copyInputStreamToFile(uploadFile.getInputStream(), file);
// 如果该目录不存在则直接创建新的目录,并切换到该目录
try {
channelSftp.cd(path);
} catch (Exception e) {
channelSftp.mkdir(path);
channelSftp.cd(path);
}
channelSftp.put(new FileInputStream(file), newName);
// 操作完成,删除刚刚生成的文件
file.delete();
}
}
8.代码测试
8.1 文件下载
http://localhost:9001/download?file=test.txt&path=/home/test
8.2 文件上传
localhost:9001/upload
总结:打完收工,各位帅哥、美女。浏览完点个赞再走哦。