springboot上傳下載檔案(4)--封裝成工具類
阿新 • • 發佈:2018-12-27
因為在做畢設,發現之前的搭建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、通過封裝成工具類,提高了程式碼的可複用性,和簡潔性