springboot项目中通过sftp连接服务器实现简单的文件上传和下载,代码注解详细。
- 新建springboot项目并在pom.xml文件中引入依赖
<!-- sftp上传依赖包 -->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.53</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
- 在application.yml中配置相关属性,注意设置multipart属性,否则可能会因为文件大小超过默认值而引起上传文件失败。
spring:
servlet:
multipart:
# 单个文件的大小不能超过该值
max-file-size: 100MB
# 单个请求最大的大小不能超过该值
max-request-size: 1000MB
# 这里也可以直接作为成员变量写死在类里。这里的配置都是我自定义的,叫什么都可以。
iosServer:
username: test
password: test
host: 172.16.92.4
port: 22
- 创建连接服务器的sftp配置类,这里为了学习springboot的配置类所以我使用了配置类,你也可以使用普通的工具类来实现它。注意如果使用了和我一样的方式,那么项目在启动时就会去连接服务器,如果连接失败或者配置错误项目就会启动失败,所以这里还是建议大家使用普通的类来实现。
package com.jiayuewen.config;
import com.jcraft.jsch.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import java.util.Properties;
/**
* @author jiayuewen
* @description 连接服务器
* @date 2020/9/12 21:40
*/
@Configuration
public class SftpConnectConfig {
/** FTP 登录用户名*/
@Value("${iosServer.username}")
private String username;
/** FTP 登录密码*/
@Value("${iosServer.password}")
private String password;
/** FTP 服务器地址IP地址*/
@Value("${iosServer.host}")
private String host;
/** FTP 端口*/
@Value("${iosServer.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");
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) {
System.out.println("连接失败");
}
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) {
System.out.println("连接失败");
}
return sftp;
}
}
- 编写下载文件的service
package com.jiayuewen.service;
import com.jcraft.jsch.ChannelSftp;
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 jiayuewen
* @description
* @date 2020/10/16 0:01
*/
@Service
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();
}
}
- 编写controller
package com.jiayuewen.controller;
import com.jiayuewen.service.FileService;
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 jiayuewen
* @description
* @date 2020/10/18 0:22
*/
@RestController
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) {
e.printStackTrace();
}
}
/**
* 上传文件到服务器
* @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) {
e.printStackTrace();
}
}
}
至此,通过sftp连接服务器实现文件上传下载就完成了,快去试试吧。
版权声明:本文为weixin_44499429原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。