package com.dxhy.oss.service; import cn.hutool.core.io.FileUtil; import com.dxhy.oss.utils.SftpPool; import com.jcraft.jsch.ChannelSftp; import com.jcraft.jsch.SftpException; import lombok.extern.slf4j.Slf4j; import org.apache.commons.net.ftp.FTP; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.nio.file.Files; import java.util.ArrayList; import java.util.List; /** * @author jiaohongyang */ @Slf4j public class FtpService { private final SftpPool pool; public FtpService(SftpPool pool) { this.pool = pool; } /** * 将输入流的数据上传到sftp作为文件。文件完整路径 = basePath+directory * * @param pathName ftp服务保存地址,完整路径 * @param fileName 上传到ftp的文件名 * @param originFileName 待上传文件的名称(绝对地址) */ public boolean uploadFile(String pathName, String fileName, String originFileName) throws InterruptedException { log.info("开始上传文件"); ChannelSftp sftp = null; InputStream inputStream; try { sftp = pool.borrowObject(); try { sftp.cd(pathName); } catch (SftpException e) { // 目录不存在,则创建文件夹 String[] dirs = pathName.split("/"); String tempPath = ""; for (String dir : dirs) { if (null == dir || "".equals(dir)) { continue; } tempPath += "/" + dir; try { sftp.cd(tempPath); } catch (SftpException ex) { try { sftp.mkdir(tempPath); sftp.cd(tempPath); } catch (SftpException e1) { e1.printStackTrace(); } } } } File orgFile = new File(originFileName); inputStream = Files.newInputStream(orgFile.toPath()); sftp.put(inputStream, fileName); inputStream.close(); // 删除本地文件,防止服务器空间不足 FileUtil.del(orgFile); log.info("上传文件成功"); return true; } catch (Exception e) { e.printStackTrace(); log.info("上传文件失败"); return false; } finally { if (sftp != null) { log.info("回收线程"); pool.returnObject(sftp); } } } public static boolean uploadFile(FTPClient ftpClient, String serviceDec, String fileName, InputStream inputStream) { try { log.info("开始上传文件"); ftpClient.setFileType(FTP.BINARY_FILE_TYPE); createDirecroty(ftpClient, serviceDec); ftpClient.makeDirectory(serviceDec); ftpClient.changeWorkingDirectory(serviceDec); ftpClient.storeFile(fileName, inputStream); inputStream.close(); ftpClient.logout(); log.info("上传文件成功"); } catch (Exception e) { log.error("上传文件失败" + e); } finally { try { if (ftpClient.isConnected()) { ftpClient.disconnect(); } if (null != inputStream) { inputStream.close(); } } catch (IOException e) { log.error("上传文件失败" + e); return false; } } return true; } private static boolean createDirecroty(FTPClient ftpClient, String remote) throws IOException { boolean success = true; String directory = remote + "/"; // 如果远程目录不存在,则递归创建远程服务器目录 if (!directory.equalsIgnoreCase("/") && !changeWorkingDirectory(ftpClient, new String(directory))) { int start = 0; int end = 0; if (directory.startsWith("/")) { start = 1; } else { start = 0; } end = directory.indexOf("/", start); String path = ""; String paths = ""; while (true) { String subDirectory = new String(remote.substring(start, end).getBytes("GBK"), "iso-8859-1"); path = path + "/" + subDirectory; if (!existFile(ftpClient, path)) { if (makeDirectory(ftpClient, subDirectory)) { changeWorkingDirectory(ftpClient, subDirectory); } else { log.info("创建目录[" + subDirectory + "]失败"); changeWorkingDirectory(ftpClient, subDirectory); } } else { changeWorkingDirectory(ftpClient, subDirectory); } paths = paths + "/" + subDirectory; start = end + 1; end = directory.indexOf("/", start); // 检查所有目录是否创建完毕 if (end <= start) { break; } } } return success; } //改变目录路径 private static boolean changeWorkingDirectory(FTPClient ftpClient, String directory) { boolean flag = true; try { flag = ftpClient.changeWorkingDirectory(directory); if (flag) { log.info("进入文件夹" + directory + " 成功!"); } else { log.info("进入文件夹" + directory + " 失败!开始创建文件夹"); } } catch (IOException ioe) { ioe.printStackTrace(); } return flag; } //判断ftp服务器文件是否存在 private static boolean existFile(FTPClient ftpClient, String path) throws IOException { boolean flag = false; FTPFile[] ftpFileArr = ftpClient.listFiles(path); if (ftpFileArr.length > 0) { flag = true; } return flag; } //创建目录 private static boolean makeDirectory(FTPClient ftpClient, String dir) { boolean flag = true; try { flag = ftpClient.makeDirectory(dir); if (flag) { log.info("创建文件夹" + dir + " 成功!"); } else { log.info("创建文件夹" + dir + " 失败!"); } } catch (Exception e) { e.printStackTrace(); } return flag; } /** * 获取FTP某一特定目录下的所有文件名称 * * @param ftpClient 已经登陆成功的FTPClient * @param ftpDirPath FTP上的目标文件路径 */ public static List getFileNameList(FTPClient ftpClient, String ftpDirPath) { List list = new ArrayList(); try { if (ftpDirPath.startsWith("/") && ftpDirPath.endsWith("/")) { // 通过提供的文件路径获取FTPFile对象列表 FTPFile[] files = ftpClient.listFiles(ftpDirPath); // 遍历文件列表,打印出文件名称 for (int i = 0; i < files.length; i++) { FTPFile ftpFile = files[i]; // 此处只打印文件,未遍历子目录(如果需要遍历,加上递归逻辑即可) if (ftpFile.isFile()) { // log.info(ftpDirPath + ftpFile.getName()); list.add(ftpFile.getName()); } } log.info("当前FTP路径可用"); } else { log.info("当前FTP路径不可用"); } } catch (IOException e) { log.error("错误" + e); } return list; } public File downloadFile(FTPClient ftpClient, String servicePath, String fileName, String localFilePath) { String name = dowFile(ftpClient, servicePath, fileName, localFilePath); if (name != null && !name.equals("")){ return new File(fileName); } return null; } private static String dowFile(FTPClient ftpClient, String servicePath, String fileName, String localFilePath) { InputStream is = null; FileOutputStream fos = null; try { ftpClient.enterLocalPassiveMode(); is = ftpClient.retrieveFileStream(servicePath + fileName);// 获取ftp上的文件 fos = new FileOutputStream(new File(localFilePath + fileName)); // 文件读取方式一 int i; byte[] bytes = new byte[1024]; while ((i = is.read(bytes)) != -1) { fos.write(bytes, 0, i); } // 文件读取方式二 //ftpClient.retrieveFile(ftpFilePath, new FileOutputStream(new File(localFilePath))); ftpClient.completePendingCommand(); log.info("FTP文件下载成功!"); } catch (Exception e) { log.error("FTP文件下载失败!" + e); } finally { try { if (fos != null) fos.close(); if (is != null) is.close(); } catch (IOException e) { log.error("下载流关闭失败" + e); return null; } } return localFilePath + fileName; } public boolean downloadFile(String directory, String downloadFile, String saveFile) { log.info("开始下载文件!"); ChannelSftp sftp = null; try { sftp = pool.borrowObject(); if (directory != null && !"".equals(directory)) { sftp.cd(directory); } String file = saveFile + "/" + downloadFile; File fileLocal = new File(file); if (fileLocal.exists()) { boolean delete = fileLocal.delete(); log.info("删除本地路径文件:{}", delete); } this.directoryIsExists(saveFile); sftp.get(downloadFile, file); log.info("下载文件成功!"); return true; } catch (Exception e) { e.printStackTrace(); log.info("下载文件失败!"); return false; } finally { if (sftp != null) { log.info("回收线程"); pool.returnObject(sftp); } } } /** * 删除文件 * * @param directory 要删除文件所在目录 * @param deleteFile 要删除的文件 * @return 返回是否删除成功 */ public boolean deleteFile(String directory, String deleteFile) { ChannelSftp sftp = null; try { sftp = pool.borrowObject(); sftp.cd(directory); sftp.rm(deleteFile); return true; } catch (Exception e) { e.printStackTrace(); return false; } finally { if (sftp != null) { log.info("回收线程"); pool.returnObject(sftp); } } } public void directoryIsExists(String path) { File directory = new File(path); if (directory.exists()) { return; } if (!directory.mkdir()) { return; } if (directory.canWrite()) { return; } boolean setWritable = directory.setWritable(true); log.info("是否创建文件 directoryIsExists :{} ", setWritable); } }