1. 程式人生 > >springboot上傳下載檔案(4)--封裝成工具類

springboot上傳下載檔案(4)--封裝成工具類

因為在做畢設,發現之前的搭建ftp檔案伺服器,通過ftp協議無法操作虛擬機器臨時檔案,又因為ftp檔案伺服器搭建的比較麻煩;而

hadoop的HDFS雖然可以實現,但我這裡用不到那麼複雜的;所以我封裝了一個檔案上傳下載的工具類,採用sftp協議.

簡單方便可用性高!!!


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、通過封裝成工具類,提高了程式碼的可複用性,和簡潔性