admin管理员组文章数量:1664345
依赖:
<dependency>
<groupId>ch.ethz.ganymed</groupId>
<artifactId>ganymed-ssh2</artifactId>
<version>build210</version>
</dependency>
首先,我们把服务器连接信息配置在yml文件中,方便后期换服务器地址时,不用修改代码,统一管理
#服务器相关信息
fileserver:
host: xxx.xxx.xxx.xxx #连接地址
port: xx #端口号
username: root #服务器登录账号
password: root #服务器密码
filePath: /app/server/forms/ #服务器文件存放地址
然后配置映射类,用来接收yml文件中配置的信息
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.stereotype.Component;
@Component
@ConfigurationProperties(prefix = "fileserver")
public class FileServerConfig {
//连接地址
private String host;
//端口号
private int port;
//登录用户名
private String username;
//登录密码
private String password;
//报表存放;路径
private String filePath;
public String getHost() {
return host;
}
public void setHost(String host) {
this.host = host;
}
public int getPort() {
return port;
}
public void setPort(int port) {
this.port = port;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
}
@ConfigurationProperties(prefix = “fileserver”)这个千万不能忘,没有这个,读取不了yml文件中的信息
下面是工具类,操作服务器用:
import ch.ethz.ssh2.Connection;
import ch.ethz.ssh2.SCPClient;
import ch.ethz.ssh2.Session;
import ch.ethz.ssh2.StreamGobbler;
import com.common.config.FileServerConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.servlet.ServletOutputStream;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.List;
/**
* 服务器操作工具类
*/
@Component
public class SshUtil {
@Autowired
private FileServerConfig fileServerConfig;
/**
* 执行传来的linux指令
*
* @param command
* @return
*/
public List<String> execCom(String command) {
Session session = getSession();
BufferedReader br = null;
List<String> msgList = new ArrayList<>();
try {
session.requestPTY("vt100", 80, 24, 640, 480, null);
session.execCommand(command);
InputStream stdout = new StreamGobbler(session.getStdout());
br = new BufferedReader(new InputStreamReader(stdout));
while (true) {
String line = br.readLine();
if (line == null) {
break;
}
msgList.add(line);
}
} catch (IOException e) {
e.printStackTrace();
}
try {
br.close();
} catch (IOException e) {
e.printStackTrace();
}
session.close();
Connection con = getCon();
con.close();
return msgList;
}
private Session getSession() {
Session session = null;
try {
Connection con = getCon();
session = con.openSession();
} catch (IOException e) {
e.printStackTrace();
return null;
}
return session;
}
/**
* 获取连接
*
* @return
*/
private Connection getCon() {
Connection con = null;
try {
con = new Connection(fileServerConfig.getHost(), fileServerConfig.getPort());
con.connect();
// 远程服务器的用户名密码
con.authenticateWithPassword(fileServerConfig.getUsername(), fileServerConfig.getPassword());
} catch (IOException e) {
e.printStackTrace();
}
return con;
}
/**
* 下载服务器文件到本地目录
* @param fileName 服务器文件
* @param localPath 本地目录
*/
public void copyFile( String fileName, String localPath){
Connection con = getCon();
SCPClient sc = new SCPClient(con);
try {
sc.get(fileName, localPath);
} catch (IOException e) {
e.printStackTrace();
}
}
/**
* 流式输出,用于浏览器下载
* @param fileName
* @param outputStream
*/
public void copyFile(String fileName, ServletOutputStream outputStream){
Connection con = getCon();
SCPClient sc = new SCPClient(con);
try {
sc.get(fileName, outputStream);
} catch (IOException e) {
e.printStackTrace();
}
}
}
下面这个工具类是用来处理文件编码问题的
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import javax.servlet.http.HttpServletResponse;
/**
* 文件处理工具类
*/
public class FileUtils extends org.apache.commons.io.FileUtils {
/**
* 下载文件名重新编码
*
* @param response 响应对象
* @param realFileName 真实文件名
* @return
*/
public static void setAttachmentResponseHeader(HttpServletResponse response, String realFileName) throws UnsupportedEncodingException {
String percentEncodedFileName = percentEncode(realFileName);
StringBuilder contentDispositionValue = new StringBuilder();
contentDispositionValue.append("attachment; filename=")
.append(percentEncodedFileName)
.append(";")
.append("filename*=")
.append("utf-8''")
.append(percentEncodedFileName);
response.setHeader("Content-disposition", contentDispositionValue.toString());
}
/**
* 百分号编码工具方法
*
* @param s 需要百分号编码的字符串
* @return 百分号编码后的字符串
*/
public static String percentEncode(String s) throws UnsupportedEncodingException {
String encode = URLEncoder.encode(s, StandardCharsets.UTF_8.toString());
return encode.replaceAll("\\+", "%20");
}
}
最后是Controller,这一步写好了,就差不多了
@RestController
@RequestMapping("/reportForms")
public class ReportFormsController{
@Resource
private SshUtil sshUtil;
@Resource
private FileServerConfig fileServerConfig;
@GetMapping("/getLinuxFile")
public void getLinuxFile(String fileName, HttpServletResponse response) throws IOException {
String path = fileServerConfig.getFilePath();
response.reset();
//设置请求头
FileUtils.setAttachmentResponseHeader(response, fileName);
//查询文件并下载
sshUtil.copyFile(path + fileName, response.getOutputStream());
}
}
注意,最重要的:如果项目访问接口需要鉴权的,那就要使下载接口忽略鉴权,否则前端无法下载,我的项目中,鉴权是在SecurityConfig这个类中:
@Override
protected void configure(HttpSecurity httpSecurity) throws Exception
{
httpSecurity
// CSRF禁用,因为不使用session
.csrf().disable()
// 认证失败处理类
.exceptionHandling().authenticationEntryPoint(unauthorizedHandler).and()
// 基于token,所以不需要session
.sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS).and()
// 过滤请求
.authorizeRequests()
// 对于登录login 验证码captchaImage 允许匿名访问
.antMatchers("/login", "/captchaImage","/userLogin").anonymous()
.antMatchers(
HttpMethod.GET,
"/*.html",
"/**/*.html",
"/**/*.css",
"/**/*.js"
).permitAll()
.antMatchers("/profile/**").anonymous()
.antMatchers("/common/download**").anonymous()
.antMatchers("/common/download/resource**").anonymous()
.antMatchers("/reportForms/getLinuxFile").anonymous()
.antMatchers("/swagger-ui.html").anonymous()
.antMatchers("/swagger-resources/**").anonymous()
.antMatchers("/webjars/**").anonymous()
.antMatchers("/*/api-docs").anonymous()
.antMatchers("/druid/**").anonymous()
// 除上面外的所有请求全部需要鉴权认证
.anyRequest().authenticated()
.and()
.headers().frameOptions().disable();
httpSecurity.logout().logoutUrl("/logout").logoutSuccessHandler(logoutSuccessHandler);
// 添加JWT filter
httpSecurity.addFilterBefore(authenticationTokenFilter, UsernamePasswordAuthenticationFilter.class);
// 添加CORS filter
httpSecurity.addFilterBefore(corsFilter, JwtAuthenticationTokenFilter.class);
httpSecurity.addFilterBefore(corsFilter, LogoutFilter.class);
}
凡是antMatchers("/reportForms/getLinuxFile").anonymous()这个里面的访问路径,都是不需要鉴权的。
参考博文:https://super.blog.csdn/article/details/84204842
版权声明:本文标题:Java 从服务器下载文件,并提供给浏览器下载 内容由热心网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:https://www.elefans.com/xitong/1730014392a1219166.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论