因为在做毕设,发现之前的搭建ftp文件服务器,通过ftp协议无法操作虚拟机临时文件,又因为ftp文件服务器搭建的比较麻烦;而

hadoop的HDFS虽然可以实现,但我这里用不到那么复杂的;所以我封装了一个文件上传下载的工具类,采用sftp协议.

简单方便可用性高!!!


目录

1、依赖

2、配置(yml)

3、SFTPUtils

4、Controller

5、总结:通过封装成工具类,提高了代码的可复用性,和简洁性


1、依赖

<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>

2、配置(yml)

sftp:
  ip: 192.168.23.142
  port: 22
  username: root
  password: 123456
  downloadSleep: 100 #文件下载失败下次超时重试时间
  downloadRetry: 10 #文件下载失败重试次数
  uploadSleep: 100 #文件上传失败下次超时重试时间
  uploadRettry: 10  #文件上传失败重试次数

3、SFTPUtils

package com.zj.docker.utils;

import com.jcraft.jsch.*;
import org.springframework.scheduling.annotation.Async;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.lang.reflect.Field;
import java.util.Properties;

/**
 * @Auther: zj
 * @Date: 2018/12/18 16:58
 * @Description:
 */
public class SFTPUtils {

    /**
     * 默认端口
     */

    private final static int DEFAULT_PORT = 22;

    private final static String HOST = "host";

    private final static String PORT = "port";

    private final static String USER_NAME = "userName";

    private final static String PASSWORD = "password";



    /**
     * 服务端保存的文件名
     */
    private String remote;

    /**
     * 服务端保存的路径
     */
    private String remotePath;

    /**
     * 本地文件
     */
    private File local;

    /**
     * 主机地址
     */
    private String host;

    /**
     * 端口
     */
    private int port = DEFAULT_PORT;

    /**
     * 登录名
     */
    private String userName;

    /**
     * 登录密码
     */
    private String password;

    private ChannelSftp sftp;


    public SFTPUtils(String host, int port, String userName, String password) {
        this.init(host, port, userName, password);
    }


    /**
     * 初始化
     *
     * @param host
     * @param port
     * @param userName
     * @param password
     * @date 2018/12/18
     */
    private void init(String host, int port, String userName, String password) {
        this.host = host;
        this.port = port;
        this.userName = userName;
        this.password = password;
    }

    /**
     * 连接sftp
     *
     * @throws JSchException
     * @date 2018/12/18
     */
    private void connect() throws JSchException, NoSuchFieldException, IllegalAccessException, SftpException {
        JSch jsch = new JSch();
        // 取得一个SFTP服务器的会话
        Session session = jsch.getSession(userName, host, port);
        // 设置连接服务器密码
        session.setPassword(password);
        Properties sessionConfig = new Properties();
        // StrictHostKeyChecking
        // "如果设为"yes",ssh将不会自动把计算机的密匙加入"$HOME/.ssh/known_hosts"文件,
        // 且一旦计算机的密匙发生了变化,就拒绝连接。
        sessionConfig.setProperty("StrictHostKeyChecking", "no");
        // 设置会话参数
        session.setConfig(sessionConfig);
        // 连接
        session.connect();
        // 打开一个sftp渠道
        Channel channel = session.openChannel("sftp");
        sftp = (ChannelSftp) channel;
        channel.connect();

        Class cl = ChannelSftp.class;
        Field f =cl.getDeclaredField("server_version");
        f.setAccessible(true);
        f.set(sftp, 2);
        sftp.setFilenameEncoding("GBK");



    }

    /**
     * 上传文件
     * @date 2018/12/18
     */
    public void uploadFile() throws Exception {
        FileInputStream inputStream = null;
        try {
            connect();
            if (isEmpty(remote)) {
                remote = local.getName();
            }
            if (!isEmpty(remotePath)) {
                sftp.cd(remotePath);
            }
            inputStream = new FileInputStream(local);
            sftp.put(inputStream, remote);
        } catch (Exception e) {
            throw e;
        } finally {
            sftp.disconnect();
            close(inputStream);
        }
    }

    public void uploadFile(InputStream inputStream) throws Exception {
        try {
            connect();
            if (isEmpty(remote)) {
                remote = local.getName();
            }
            if (!isEmpty(remotePath)) {
                createDir(remotePath);
            }

            sftp.put(inputStream, remote);
        } catch (Exception e) {
            throw e;
        } finally {
            sftp.disconnect();
            close(inputStream);
        }
    }

    @Async("taskExecutor")//异步
    public void uploadFile(String filename, String filePath, MultipartFile file) throws Exception {
        try {
            connect();
            if (!isEmpty( filePath )) {
                createDir( filePath );
            }
            sftp.put( file.getInputStream(), filename );
        }catch (Exception e) {
            throw e;
        } finally {
            sftp.disconnect();
            close(file.getInputStream());
        }

    }

    public boolean isDirExist(String directory) throws Exception {
        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;
    }

    public void createDir(String createpath) throws Exception {
        try {
            if (isDirExist(createpath)) {
                this.sftp.cd(createpath);
            } else {
                String pathArry[] = createpath.split("/");

                for (String path : pathArry) {
                    if (path.equals("")) {
                        continue;
                    }

                    if (isDirExist(path.toString())) {
                        sftp.cd(path.toString());
                    } else {
                        // 建立目录
                        sftp.mkdir(path.toString());
                        // 进入并设置为当前目录
                        sftp.cd(path.toString());
                    }
                }

            }
        } catch (SftpException e) {
            throw new Exception("创建路径错误:" + createpath);
        }
    }

    /**
     * 下载
     * @date 2018/12/18
     */
    public void download() throws Exception {
        FileOutputStream output = null;
        try {
            this.connect();
            if (null != remotePath || !("".equals(remotePath))) {
                sftp.cd(remotePath);
            }
            output = new FileOutputStream(local);
            sftp.get(remote, output);
        } catch (Exception e) {
            throw e;
        } finally {
            sftp.disconnect();
            close(output);
        }
    }

    public void download(OutputStream outputStream) throws Exception {

        try {
            this.connect();
            if (null != remotePath || !("".equals(remotePath))) {
                sftp.cd(remotePath);
            }
            sftp.get(remote, outputStream);
        } catch (Exception e) {
            throw e;
        } finally {
            sftp.disconnect();
        }
    }

    public static boolean isEmpty(String str) {
        if (null == str || "".equals(str)) {
            return true;
        }
        return false;
    }

    public static void close(OutputStream... outputStreams) {
        for (OutputStream outputStream : outputStreams) {
            if (outputStream != null) {
                try {
                    outputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public static void close(InputStream... inputStreams) {
        for (InputStream inputStream : inputStreams) {
            if (inputStream != null) {
                try {
                    inputStream.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    public void setRemote(String remote) {
        this.remote = remote;
    }

    public void setRemotePath(String remotePath) {
        this.remotePath = remotePath;
    }

    public void setLocal(File local) {
        this.local = local;
    }


}

4、Controller

测试,这边就简单举了一个例子

@Value("${sftp.ip}")
    private String SFTP_ADDRESS; //ip

    @Value("${sftp.port}")
    private Integer SFTP_PORT; //port

    @Value("${sftp.username}")
    private String SFTP_USERNAME; //sftp username

    @Value("${sftp.password}")
    private String SFTP_PASSWORD; //sftp password

--------------------------------------------------


 /**
     * 上传文件到数据卷,普通用户权限
     * @param request
     * @param name 数据卷的名称
     * @param file 上传的文件
     * @return
     * @throws Exception
     */
    @PostMapping("/customer/uploadDocToVolume")
    public ResultVo customerUploadDocToVolume(HttpServletRequest request,
                                              @RequestParam("name") String name,
                                              @RequestParam("file") MultipartFile file
                                              ) throws Exception {
        //鉴权
        String username = userRoleAuthentication.getUsernameAndAutenticateUserRoleFromRequest( request, RoleEnum.User.getMessage() );
        if (Objects.equals( username, CommonEnum.FALSE.getMessage())) {
            return ResultVoUtil.error();
        }
        //校验参数
        if (StringUtils.isBlank( name )||file==null ) {
            return ResultVoUtil.error(CommonEnum.PARAM_ERROR.getMessage());
        }

        String bashPath ="/var/lib/docker/volumes/";
        String picSavePath = "/"+name+"/_data";


        SFTPUtils sftpUtils = new SFTPUtils( SFTP_ADDRESS,SFTP_PORT,SFTP_USERNAME,SFTP_PASSWORD);
        //上传文件,同步
        sftpUtils.uploadFile( file.getOriginalFilename(),bashPath+picSavePath,file );

        return ResultVoUtil.success("上传文件成功");
    }

5、总结

通过封装成工具类,提高了代码的可复用性,和简洁性