admin管理员组

文章数量:1664339

依赖:

<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