上传文件到服务器(Java)

一、本项目核心目的(目前支持.sql 和 .py脚本,.java脚本跟.py脚本大同小异,只是命令不同)1.从A服务器获取脚本文件2.上传到B服务器指定文件夹3.通过命令执行上传后得脚本文件4.返回执行结果二、核心jar包<!–sftp文件上传–>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
<!–ssh执行–>
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>三、Spring Boot 与 nacos 版本不对应时会报错,当前Spring Boot版本为2.3.9.RELEASE四、pom.xml 文件<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>262</version>
</dependency>
<dependency>
<groupId>com.alibaba.boot</groupId>
<artifactId>nacos-config-spring-boot-starter</artifactId>
<version>0.2.7</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.18.20</version>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-web</artifactId>
<version>5.2.12.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-commons</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-context</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<!–sftp文件上传–>
<dependency>
<groupId>com.jcraft</groupId>
<artifactId>jsch</artifactId>
<version>0.1.54</version>
</dependency>
</dependencies>五、RemoteCommandConfig(服务器调用)import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.alibaba.fastjson.JSONObject;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Component;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;

@Slf4j
@Component
public class RemoteCommandConfig {

/**
* 只是用来测试,无其他用处
*/
public static void main(String[] args) {
Connection conn = login("这里填服务器IP地址", "账号", "密码");
JSONObject execute = execute(conn, "cd /script/ &&mysql -vvv -uadmin -p123456 spring_data < 测试.sql");
System.out.println(execute.toString());
}

private static String DEFAULTCHART = "UTF-8";

/**
* @return 登录成功返回true,否则返回false
* @描述 登录主机
*/
public static Connection login(String ip, String username, String password) {
boolean flg;
Connection conn = null;
try {
conn = new Connection(ip);
conn.connect();//连接
flg = conn.authenticateWithPassword(username, password);//认证
if (flg) {
return conn;
}
} catch (IOException e) {
log.error("脚本执行登录服务器失败,error={}" + e.getMessage());
e.printStackTrace();
}
return conn;
}

/**
* @param cmd 即将执行的命令
* @return 命令执行完后返回的结果值
* @描述 远程执行shll脚本或者命令
*/
public static JSONObject execute(Connection conn, String cmd) {
JSONObject result = new JSONObject();
result.put("code", 200);
String str = "";
try {
if (conn != null) {
Session session = conn.openSession();//打开一个会话
session.execCommand(cmd);//执行命令
str = processStdout(session.getStdout(), DEFAULTCHART);
//如果为得到标准输出为空,说明脚本执行出错了
if (StringUtils.isBlank(str)) {
result.put("code", 400);
result.put("msg", "得到标准输出为空,链接conn:" + conn + ",执行的命令:" + cmd);
str = processStdout(session.getStderr(), DEFAULTCHART);
} else {
result.put("msg", 200);
result.put("msg", "执行命令成功,链接conn:" + conn + ",执行的命令:" + cmd);
}
conn.close();
session.close();
}
} catch (IOException e) {
log.info("执行命令失败,链接conn:" + conn + ",执行的命令:" + cmd + " error={}" + e.getMessage());
}
result.put("data", str);
return result;
}

/**
* @param in 输入流对象
* @param charset 编码
* @return 以纯文本的格式返回
* @描述 解析脚本执行返回的结果集
*/
private static String processStdout(InputStream in, String charset) {
InputStream stdout = new StreamGobbler(in);
StringBuffer buffer = new StringBuffer();
try {
BufferedReader br = new BufferedReader(new InputStreamReader(stdout, charset));
String line;
while ((line = br.readLine()) != null) {
buffer.append(line + "\n");
}
} catch (Exception e) {
log.error("解析脚本出错,error={}" + e.getMessage());
e.printStackTrace();
}
return buffer.toString();
}六、RestTemplateConfig防止项目因为RestTemplate启动失败import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.cloud.client.loadbalancer.LoadBalanced;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.web.client.RestTemplate;

@Configuration
public class RestTemplateConfig {
@Bean
@LoadBalanced
public RestTemplate restTemplate(RestTemplateBuilder builder){
return builder.build();
}
}七、ScriptDealWithController (方法整合)import ch.ethz.ssh2.Connection;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.nacos.api.config.annotation.NacosValue;
import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.Session;
import com.sd.config.RemoteCommandConfig;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.*;
import org.springframework.util.CollectionUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import java.io.OutputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

//nacos实时动态参数获取
@RefreshScope
@RestController
@RequestMapping("/script")
public class ScriptDealWithController {
/**
* 本项目所在服务器地址
*/
@NacosValue(value = "${gyyh_login.ip}")
private String gyyhIP;//登录获取ip
@NacosValue(value = "${gyyh_login.username}")
private String gyyhUsername;//系统账号
@NacosValue(value = "${gyyh_login.password}")
private String gyyhPassword;//系统密码
/**
* MySQL服务器地址
*/
@NacosValue(value = "${mysql_script.ip}")
private String myIp;//MySQL所在ip
@NacosValue(value = "${mysql_script.username}")
private String myUsername;//MySQL所在ip账号
@NacosValue(value = "${mysql_script.password}")
private String myPassword;//MySQL所在ip密码
@NacosValue(value = "${mysql_script.command}")
private String myCommand;//MySQL脚本执行命令
@NacosValue(value = "${mysql_script.file_path}")
private String myFilePath;//文件保存路径
/**
* pythonL服务器地址
*/
@NacosValue(value = "${python_script.ip}")
private String pyIp;//MySQL所在ip
@NacosValue(value = "${python_script.username}")
private String pyUsername;//MySQL所在ip账号
@NacosValue(value = "${python_script.password}")
private String pyPassword;//MySQL所在ip密码
@NacosValue(value = "${python_script.command}")
private String pyCommand;//MySQL脚本执行命令
@NacosValue(value = "${python_script.file_path}")
private String pyFilePath;//文件保存路径

@Autowired
private RestTemplate restTemplate;

/**
* @描述 获取平台登录token
* @参数 []
* @返回值 java.lang.String
* @创建时间 2021/7/23
*/
public String getToken() {
String url = gyyhIP + "/获取token地址";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
MultiValueMap<String, String> params = new LinkedMultiValueMap<>();
params.add("username", gyyhUsername);
params.add("password", gyyhPassword);
HttpEntity<MultiValueMap<String, String>> requestEntity = new HttpEntity<>(params, headers);
ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, requestEntity, String.class);
JSONObject body = JSON.parseObject(response.getBody());
JSONObject data = body.getJSONObject("data");
if (CollectionUtils.isEmpty(data)) {
throw new RuntimeException("token获取失败");
}
return data.getString("token");
}

/**
* @描述 调用平台文件下载接口获取文件流
* @参数 [body]
* @返回值 byte[]
* @创建时间 2021/7/23
*/
public byte[] download(String token, String type, String downloadId) {
String url = gyyhIP + "文件下载接口地址";
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_JSON);
headers.set("Authorization", token);
Map<String, String> params = new HashMap<>();
params.put("type", type);
params.put("downloadId", downloadId);
HttpEntity<Map<String, String>> requestEntity = new HttpEntity<>(params, headers);
ResponseEntity<byte[]> response = restTemplate.postForEntity(url, requestEntity, byte[].class);
return response.getBody();
}

/**
* @描述 写入文件到指定目录下
* @参数 [bfile, filePath, fileName]
* @返回值 void
* @创建时间 2021/7/23
*/
public void upload(byte[] bfile, String ip, String username, String password, String filePath, String fileName) throws Exception {
//服务器端口 默认22
int port = 22;
Session session = null;
Channel channel = null;
JSch jsch = new JSch();
if (port <= 0) {
//连接服务器,采用默认端口
session = jsch.getSession(username, myIp);
} else {
//采用指定的端口连接服务器
session = jsch.getSession(username, ip, port);
}
//如果服务器连接不上,则抛出异常
if (session == null) {
throw new Exception("session is null");
}
//设置登陆主机的密码
session.setPassword(password);//设置密码
//设置第一次登陆的时候提示,可选值:(ask | yes | no)
session.setConfig("StrictHostKeyChecking", "no");
//设置登陆超时时间
session.connect(30000);
OutputStream outstream = null;
try {
//创建sftp通信通道
channel = session.openChannel("sftp");
channel.connect(1000);
ChannelSftp sftp = (ChannelSftp) channel;
//进入服务器指定的文件夹
sftp.cd(filePath);
//以下代码实现从本地上传一个文件到服务器,如果要实现下载,对换以下流就可以了
outstream = sftp.put(fileName);
outstream.write(bfile);
} catch (Exception e) {
e.printStackTrace();
} finally {
//关流操作
if (outstream != null) {
outstream.flush();
outstream.close();
}
if (session != null) {
session.disconnect();
}
if (channel != null) {
channel.disconnect();
}
}
}

/**
* @描述 脚本执行
* @参数 [body]
* @返回值 java.lang.String
* @创建时间 2021/7/27
*/
@PostMapping("/execute")
public JSONObject execute(@RequestBody JSONObject body) throws Exception {
String fileName = "";
String type = body.getString("type");
String downloadId = body.getString("downloadId");
//脚本类型 sql 、python
String languageType = body.getString("languageType");
Connection conn = null;
//执行脚本
String cmd = "";

//获取平台登录token
String token = getToken();
//调用平台文件下载接口获取文件流
byte[] download = download(token, type, downloadId);
if (StringUtils.equals("sql", languageType)) {
cmd = myCommand;
fileName = new Date().getTime() + ".sql";
conn = RemoteCommandConfig.login(myIp, myUsername, myPassword);
//写入文件到sql服务器指定目录下
upload(download, myIp, myUsername, myPassword, myFilePath, fileName);
} else if (StringUtils.equals("python", languageType)) {
cmd = pyCommand;
fileName = new Date().getTime() + ".py";
conn = RemoteCommandConfig.login(pyIp, pyUsername, pyPassword);
//写入文件到py服务器指定目录下
upload(download, pyIp, pyUsername, pyPassword, pyFilePath, fileName);
}
//执行脚本
return RemoteCommandConfig.execute(conn, cmd + fileName);
}
}
八、启动类import com.alibaba.nacos.api.config.ConfigType;
import com.alibaba.nacos.spring.context.annotation.config.NacosPropertySource;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
@NacosPropertySource(dataId = "script_****", type = ConfigType.YAML,groupId = "DEFAULT_GROUP",autoRefreshed = true)
public class ScriptDealWithApplication {

public static void main(String[] args) {
SpringApplication.run(ScriptDealWithApplication.class, args);
}

}九、application.yml配置server:
port: 8001
nacos:
config:
server-addr: 101.***.**.**:8848 #Nacos 链接地址
namespace: 55572fea-***-********************* #Nacos 命名空间ID
十、nacos配置gyyh_login:
ip: http://101.***.***.***:8088/
username: admin
password: 123456
mysql_script:
ip: 192.168.**.***
username: root
password: vagrant
file_path: /usr/local/script/
command: cd /usr/local/script/ &&mysql -vvv -uroot -p123456 spring_data <
python_script:
ip: 192.168.**.***
username: root
password: vagrant
file_path: /usr/local/script/
command: python /usr/local/script/

本文出自快速备案,转载时请注明出处及相应链接。

本文永久链接: https://www.175ku.com/26681.html