package com.example.fms.service; import cn.hutool.core.io.FileUtil; import cn.hutool.core.util.IdUtil; import com.example.fms.common.model.dto.SystemFileDTO; import com.example.fms.common.model.vo.ConfigSettingVO; import com.example.fms.common.utils.FileUtils; import com.example.fms.common.utils.SFTP; import com.jcraft.jsch.*; import lombok.RequiredArgsConstructor; import lombok.extern.slf4j.Slf4j; import org.apache.poi.util.IOUtils; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import java.io.*; import java.util.Properties; /** * sftp配置 * * @Author xiexiang * @Date 2023/6/7 */ @RequiredArgsConstructor @Slf4j @Service public class SftpService { /** * 建立连接 * * @param s * @param configSettingVO * @throws Exception */ public static void getConnect(SFTP s, ConfigSettingVO configSettingVO) throws Exception { //** 密钥的密码 */ // String privateKey ="key"; // /** 密钥文件路径 */ // String passphrase ="path"; //主机 String host = configSettingVO.getName(); //端口 int port = 22; //用户名 String username = configSettingVO.getUserName(); //密码 String password = configSettingVO.getPassword(); //会话初始化 Session session = null; //连接通道初始化 Channel channel = null; //sftp操作类初始化 ChannelSftp sftp = null; JSch jsch = new JSch(); //设置密钥和密码 //支持密钥的方式登陆,只需在jsch.getSession之前设置一下密钥的相关信息 // if (privateKey != null && !"".equals(privateKey)) { // if (passphrase != null && "".equals(passphrase)) { // //设置带口令的密钥 // jsch.addIdentity(privateKey, passphrase); // } else { // //设置不带口令的密钥 // jsch.addIdentity(privateKey); // } // } session = jsch.getSession(username, host, port); session.setPassword(password); Properties config = new Properties(); config.put("StrictHostKeyChecking", "no"); // 不验证 HostKey session.setConfig(config); try { session.connect(60000); } catch (Exception e) { if (session.isConnected()) session.disconnect(); } channel = session.openChannel("sftp"); try { channel.connect(); } catch (Exception e) { if (channel.isConnected()) channel.disconnect(); } sftp = (ChannelSftp) channel; s.setChannel(channel); s.setSession(session); s.setSftp(sftp); } /** * 断开连接 * * @param session * @param channel * @param sftp * @throws Exception */ public static void disConn(Session session, Channel channel, ChannelSftp sftp) throws Exception { if (null != sftp) { sftp.disconnect(); sftp.exit(); sftp = null; } if (null != channel) { channel.disconnect(); channel = null; } if (null != session) { session.disconnect(); session = null; } } /** * 上传文件 * * @param directory 上传的目录-相对于SFPT设置的用户访问目录, * 为空则在SFTP设置的根目录进行创建文件(除设置了服务器全磁盘访问) * @param multipartFile 要上传的文件 * @param configSettingVO 配置的信息 * @return systemFileDTO */ public static SystemFileDTO upload(String directory, MultipartFile multipartFile, ConfigSettingVO configSettingVO) throws Exception { SystemFileDTO systemFileDTO = new SystemFileDTO(); SFTP s = new SFTP(); //建立连接 getConnect(s, configSettingVO); Session session = s.getSession(); Channel channel = s.getChannel(); //sftp操作类 ChannelSftp sftp = s.getSftp(); try { try { //进入目录 sftp.cd(directory); } catch (SftpException sException) { //指定上传路径不存在 if (sftp.SSH_FX_NO_SUCH_FILE == sException.id) { //创建目录 sftp.mkdir(directory); //进入目录 sftp.cd(directory); } } //将传入的multipartFile转为所需要的file File file = FileUtils.multipartFileToFile(multipartFile); //定义文件名随机生成 String fileName = IdUtil.simpleUUID(); //重命名 file = FileUtil.rename(file, fileName, true, true); InputStream in = new FileInputStream(file); sftp.put(in, file.getName()); in.close(); FileUtils.deleteQuietly(file); //获取文件的后缀,不带“.”,必须是multipartFile类型 String extName = FileUtil.extName(multipartFile.getOriginalFilename()); //拼接文件完整名存入数据库表 String name = fileName + "." + extName; systemFileDTO.setFileName(name); systemFileDTO.setFileLength(Long.toString(file.length())); systemFileDTO.setIsDelete(0); } catch (Exception e) { throw new Exception(e.getMessage(), e); } finally { disConn(session, channel, sftp); } return systemFileDTO; } /** * 下载文件 * * @param directory 下载目录 根据SFTP设置的根目录来进行传输 * @param downloadFile 下载的文件名 * // * @param saveFile 存在本地的路径 * @param configSettingVO * @throws Exception */ public static byte[] download(String directory, String downloadFile, ConfigSettingVO configSettingVO) throws Exception { SFTP s = new SFTP(); //建立连接 getConnect(s, configSettingVO); Session session = s.getSession(); Channel channel = s.getChannel(); //sftp操作类 ChannelSftp sftp = s.getSftp(); try { //进入目录 sftp.cd(directory); //sftp.cd(directory.substring(0, directory.indexOf("/pas"))); // File file = new File(saveFile); // boolean bFile; // bFile = false; // bFile = file.exists(); // if (!bFile) { // //创建目录 // bFile = file.mkdirs(); // } InputStream is = sftp.get(downloadFile); byte[] fileData = IOUtils.toByteArray(is); // OutputStream out = new FileOutputStream(new File(saveFile, downloadFile)); // sftp.get(downloadFile, out); // out.flush(); // out.close(); is.close(); return fileData; } catch (Exception e) { throw new Exception(e.getMessage(), e); } finally { disConn(session, channel, sftp); } } /** * 删除文件 * * @param directory * @param deleteFile * @param configSettingVO * @throws Exception */ public static void delete(String directory, String deleteFile, ConfigSettingVO configSettingVO) throws Exception { SFTP s = new SFTP(); //建立连接 getConnect(s, configSettingVO); Session session = s.getSession(); Channel channel = s.getChannel(); //sftp操作类 ChannelSftp sftp = s.getSftp(); try { //需要删除的目录的上一级 sftp.cd(directory); //删除目录 sftp.rm(deleteFile); } catch (Exception e) { throw new Exception(e.getMessage(), e); } finally { disConn(session, channel, sftp); } } }