java上传文件到指定服务器

发布时间 2023-10-23 13:44:39作者: Xproer-松鼠

Java上传文件到指定主机
必须条件
先决条件是要知道上传到指定的主机,需要知道它的用户密码。

代码
pom.xml
<!--图片上传到服务器需要的依赖-->
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>

application.yml 配置文件
customize:
remoteServer:
sftp:
SFTP_httpBaseUrl: /images/ # 访问附件的地址添加 一个映射 如 /images/ -》 /server-images/
SFTP_httpPort: 80 # 公网访问的端口
SFTP_directory: /server-images/ #主机保存附件目录
SFTP_host: 192.168.1.10 #主机
SFTP_port: 22 #端口号
SFTP_username: root #用户名
SFTP_password: 123456 #密码

上传文件的工具类
package com.cfl.jd.util;

import com.jcraft.jsch.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.time.LocalDate;
import java.util.Properties;
import java.util.UUID;


/**
* 类描述:
* 上传文件到服务器的 工具类
*
* @ClassName SFTPUtil
* @Author msi
* @Date 2020/9/2 23:29
* @Version 1.0
*/
@Component
public class SFTPUtil {

/**
* 返回公网访问的地址前缀
*/
@Value("${customize.remoteServer.sftp.SFTP_httpBaseUrl}")
protected String baseUrl;
/**
* 公网访问的端口
*/
@Value("${customize.remoteServer.sftp.SFTP_httpPort}")
protected int port;
/**
* 主机保存的目录
*/
@Value("${customize.remoteServer.sftp.SFTP_directory}")
protected String directory;
/**
* 主机的IP
*/
@Value("${customize.remoteServer.sftp.SFTP_host}")
protected String host;
/**
* ssh端口
*/
@Value("${customize.remoteServer.sftp.SFTP_port}")
protected int sshPort;
/**
* 用户名
*/
@Value("${customize.remoteServer.sftp.SFTP_username}")
protected String username;
/**
* 密码
*/
@Value("${customize.remoteServer.sftp.SFTP_password}")
protected String password;

/**
* 上传多文件到指定远程主机
* @param files 文件数组
* @return list
*/
public List<String> uploadMultipartFilesToServer(MultipartFile[] files) throws SftpException, JSchException, IOException {
List<String> list = new ArrayList<>();
ChannelSftp sftp = null;
Session session = null;
sftp = this.connect(this.host, this.sshPort, this.username, this.password);
session = sftp.getSession();
for (int i = 0; i < files.length; i++) {
String originalFilename = files[i].getOriginalFilename();
// 生成文件夹名 yyyy-mm
String relativePath = new StringBuilder().append(LocalDate.now().getYear())
.append("-").append(LocalDate.now().getMonthValue()).toString();

String uuid = UUID.randomUUID().toString().replace("-", "").toLowerCase();

int lastIndex = originalFilename.lastIndexOf(".");
String fileSuffix = originalFilename.substring(lastIndex);
String filePrefix = originalFilename.substring(0, lastIndex);
String fileName = new StringBuilder().append(filePrefix).append(uuid).append(fileSuffix).toString();

// 文件上层目录
String directory = this.directory + relativePath;
// 创建文件夹
this.createDir(directory, sftp);
// 进入文件夹内
sftp.cd(directory);
// 创建文件
sftp.put(files[0].getInputStream(), fileName);
// 拼接返回格式
String s = new StringBuilder("http://").append(this.host).append(":").append(this.port)
.append(this.baseUrl).append(relativePath).append("/").append(fileName).toString();

list.add(s);
}
// 关掉连接
sftp.disconnect();
sftp.getSession().disconnect();

return list;
}

/**
* 建立连接
* @param host 主机
* @param port 端口
* @param username 用户名
* @param password 密码
* @return
*/
public ChannelSftp connect(String host, int port, String username,
String password) {
ChannelSftp sftp = null;
try {
JSch jsch = new JSch();
jsch.getSession(username, host, port);
Session sshSession = jsch.getSession(username, host, port);
sshSession.setPassword(password);
Properties sshConfig = new Properties();
sshConfig.put("StrictHostKeyChecking", "no");
sshSession.setConfig(sshConfig);
sshSession.connect();
Channel channel = sshSession.openChannel("sftp");
channel.connect();
sftp = (ChannelSftp) channel;
} catch (Exception e) {
e.printStackTrace();
}
return sftp;
}

/**
* 创建目录
*
*/
public void createDir(String createpath, ChannelSftp sftp) {
try {
if (isDirExist(sftp, createpath)) {
sftp.cd(createpath);
}
String pathArry[] = createpath.split("/");
StringBuffer filePath = new StringBuffer("/");
// 循环创建目录
for (String path : pathArry) {
if (path.equals("")) {
continue;
}
filePath.append(path + "/");
if (isDirExist(sftp, filePath.toString())) {
sftp.cd(filePath.toString());
} else {
// 建立目录
sftp.mkdir(filePath.toString());
// 进入并设置为当前目录
sftp.cd(filePath.toString());
}
}
sftp.cd(createpath);
} catch (SftpException e) {
e.printStackTrace();
}
}


/**
* 判断目录是否存在
*/
public boolean isDirExist(ChannelSftp sftp, String directory) {
boolean isDirExistFlag = false;
try {
SftpATTRS sftpATTRS = sftp.lstat(directory);
isDirExistFlag = true;
return sftpATTRS.isDir();
} catch (Exception e) {
if (e.getMessage().toLowerCase().equals("no such file")) {
isDirExistFlag = false;
}
}
return isDirExistFlag;
}
}

最后调用方式如下:
@Autowired
private UpdateFileUtil sftpUtil;
/**
* 上传文件到服务器
*
* @param files 图片
* @return
*/
@PostMapping("/file")
public Result<List<String>> file(MultipartFile[] files) throws Exception {
List<String> paths = sftpUtil.uploadMultipartFilesToServer(files);
return Result.ofSuccess(paths);
}

结语
温馨提示,如果不是强制要求上传附件到远程主机,那么不建议这样使用。因为这样会使得服务器的账号密码泄露(可以创建一个访问指定文件夹的账号,用作shell 连接)。

 

参考文章:http://blog.ncmem.com/wordpress/2023/10/23/java%e4%b8%8a%e4%bc%a0%e6%96%87%e4%bb%b6%e5%88%b0%e6%8c%87%e5%ae%9a%e6%9c%8d%e5%8a%a1%e5%99%a8/

欢迎入群一起讨论