背景

最近项目上需要实现一个功能:文件通过sftp的方式上传到服务器,找出了以前写的代码,整理了下能用,这里我用电脑虚拟机上的服务器来做目标服务器了。具体实现往下面看吧!

实现步骤

  1. 首先你得有一个项目能跑起来,我这里用的是springboot项目(没有的可以新建一个,这里就不多说了)。

  2. 接下来要配置sftp的账号、密码、ip、端口、以及要上传到目标服务器的路径,要保证是能连接通的。可以选择将这些数据放在数据库,也可以放在配置文件里。我这里是放在resources下的application.properties这个配置文件中了。

  3. 配置文件以及工具类的目录。在这里插入图片描述

  4. 这里是命名的一些属性,填写目标服务器对应的属性即可。
    在这里插入图片描述

  5. 添加获取配置文件的工具类。
    主要代码截图:
    在这里插入图片描述

  6. 添加实现sftp上传到服务器的工具类。
    主要代码截图:
    在这里插入图片描述

  7. 控制层测试方法,因为没有写前端代码,所以这里将本地文件模拟成从前端传来的MultipartFile文件类型,达到同等效果。我这里还加了异步调用,可以忽略哈。
    主要代码截图:
    在这里插入图片描述

  8. 调用接口,上传成功后可以在目标服务器对应文件夹下看到已经上传成功了。

    9.需要用到的jar依赖

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-web</artifactId>
		</dependency>
		<dependency>
			<groupId>com.jcraft</groupId>
			<artifactId>jsch</artifactId>
			<version>0.1.54</version>
		</dependency>
		<dependency>
			<groupId>commons-fileupload</groupId>
			<artifactId>commons-fileupload</artifactId>
			<version>1.3</version>
		</dependency>

效果

  1. postman调用接口方法。
    在这里插入图片描述
  2. 上传成功结果展示。
    在这里插入图片描述

附录代码

完整代码如下:

  1. SftpUtils.java工具类。
package com.tech.hssi.util;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelSftp;
import com.jcraft.jsch.JSch;

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

import javax.annotation.PostConstruct;
import java.io.InputStream;
import java.util.Properties;

/**
 * @ClassName SftpUtils
 * @Description 文件上传到sftp
 * @Author Jin
 * @Date 2020/5/7 16:51
 * @Version 1.0
 **/
public class SftpUtils {
    
    /**
     * 连接sftp服务器
     *
     * @throws Exception
     */
    public static void uploadToSFTP(String newFileName, MultipartFile file) {
        Session session = null;
        Channel channel = null;
        try {
            String propPath = "src/main/resources/application.properties";
            PropertiesReader.readProperties(propPath);
            String path = PropertiesReader.getKey("sftp.path");
            String ip = PropertiesReader.getKey("sftp.ip");
            String port = PropertiesReader.getKey("sftp.port");
            String username = PropertiesReader.getKey("sftp.username");
            String password = PropertiesReader.getKey("sftp.password");
            //sftp上的路径
            String sftpFileName = path + newFileName;
            // 创建JSch对象
            JSch jsch = new JSch();
            // 根据用户名,主机ip,端口获取一个Session对象
            session = jsch.getSession(username, ip, Integer.valueOf(port));
            session.setPassword(password);
            Properties config = new Properties();
            config.put("StrictHostKeyChecking", "no");
            // 为Session对象设置properties
            session.setConfig(config);
            // 通过Session建立链接
            session.connect();
            // 打开SFTP通道
            channel = session.openChannel("sftp");
            // 建立SFTP通道的连接
            channel.connect();
            InputStream is = file.getInputStream();
            ((ChannelSftp) channel).put(is, sftpFileName);
            is.close();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            logoutSFTP(channel, session);
        }
    }

    /**
     * 关闭sftp服务器
     *
     * @throws Exception
     */
    public static void logoutSFTP(Channel channel, Session session) {
        if (channel != null) {
            channel.disconnect();
        }
        if (session != null) {
            session.disconnect();
        }
    }


}

  1. PropertiesReader.java工具类。
package com.tech.hssi.util;

import com.sun.javafx.logging.Logger;
import org.apache.commons.logging.Log;

import java.io.*;
import java.util.Properties;

/**
 * @ClassName PropertiesReader
 * @Description 读取配置文件类
 * @Author Jin
 * @Date 2020/5/8 10:57
 * @Version 1.0
 **/
public class PropertiesReader {
    /**
     * 配置文件
     */
    private static Properties properties = new Properties();

    /**
     * 读取 properties 测试项目配置文件
     *
     * @param propertiesPath 配置文件路径
     * @return Properties
     * @throws IOException IOException
     */
    public static Properties readProperties(String propertiesPath) throws IOException {
        System.out.println("读取项目配置文件");
        InputStream inputStream = new FileInputStream(propertiesPath);
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream, "utf-8");
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader);
        properties.load(bufferedReader);
        return properties;
    }

    /**
     * 依据键名获取配置文件中的键值
     *
     * @param key 键名
     * @return 键值
     */
    public static String getKey(String key) {
        return properties.getProperty(key);
    }
}

  1. controller层方法调用。
@RequestMapping(value = "/test")
    public OprResult resultString() {
        try {
            //将本地文件模拟成从前端传来的MultipartFile文件类型
            File f = new File("C:\\Users\\AAS\\Desktop\\xxx.xlsx");
            FileItem fileItem = new DiskFileItem("mainFile", Files.probeContentType(f.toPath()), false, f.getName(), (int) f.length(), f.getParentFile());
            InputStream input = new FileInputStream(f);
            OutputStream os = fileItem.getOutputStream();
            IOUtils.copy(input, os);
            MultipartFile mulFile = new CommonsMultipartFile(fileItem);
            SftpUtils.uploadToSFTP("test.xlsx",mulFile);
            return OprResult.info("异步我先返回了");
        }catch (Exception e) {
            e.printStackTrace();
        }
        return OprResult.error("上传失败",new Throwable());
    }

结语

花了一下午的时候将这个功能测试好了,中间遇到了两个问题,这里简单说下:

  1. 获取配置文件属性时无法获取到,所以才写了个获取配置文件的工具类。
  2. 模拟前端发送请求时将File类转换成MultipartFile类。

送给亲爱的你

想牵你的手,一起到一个叫永远的地方,看天长地久的风景,尝海枯石烂的味道。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐