1. 引入喜闻乐见的maven地址
1 <dependency> 2 <groupId>commons-net</groupId> 3 <artifactId>commons-net</artifactId> 4 <version>3.6</version> 5 </dependency>
2. 代码实现
1 import lombok.extern.slf4j.Slf4j; 2 import org.apache.commons.lang3.StringUtils; 3 import org.apache.commons.net.ftp.FTPClient; 4 import org.apache.commons.net.ftp.FTPFile; 5 import org.apache.commons.net.ftp.FTPReply; 6 7 import java.io.*; 8 import java.time.LocalDate; 9 import java.util.Objects; 10 11 /** 12 * @author <a herf="mailto:yanwu0527@163.com">XuBaofeng</a> 13 * @date 2019-08-26 14:22. 14 * <p/> 15 * description: 简单操作FTP工具类 16 */ 17 @Slf4j 18 public class FtpUtil { 19 20 private static final String DEFAULT_PATH = "test"; 21 private static final String SEPARATOR = "/"; 22 23 private static final String FTP_HOST = "192.168.1.158"; 24 private static final Integer FTP_PORT = 21; 25 private static final String USERNAME = "hoolink"; 26 private static final String PASSWORD = "hoolink123"; 27 28 private static FTPClient ftpClient; 29 private static FtpUtil instance; 30 31 private FtpUtil() { 32 } 33 34 static { 35 instance = new FtpUtil(); 36 ftpClient = new FTPClient(); 37 } 38 39 /** 40 * 获取工具类示例 41 * 42 * @return FtpUtil 43 */ 44 public static FtpUtil getInstance() { 45 return instance; 46 } 47 48 /** 49 * 初始化FTP 50 */ 51 private void initClient(String host, Integer port, String username, String password) { 52 if (StringUtils.isBlank(host)) { 53 throw new RuntimeException("init ftp client failed, host is null"); 54 } 55 // ----- 当端口为空时使用默认端口 56 port = port == null ? FTP_PORT : port; 57 try { 58 ftpClient.setControlEncoding("UTF-8"); 59 // ----- 连接 60 ftpClient.connect(host, port); 61 ftpClient.login(username, password); 62 // ----- 检测连接是否成功 63 if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) { 64 log.info(" ----- connect success ftp server host: {}, post: {}, user: {}", host, port, username); 65 return; 66 } 67 log.error(" ----- connect failed ftp server host: {}, post: {}, user: {}", host, port, username); 68 } catch (Exception e) { 69 log.error(" ----- connect failed ftp server, ", e); 70 } 71 instance.close(); 72 } 73 74 /** 75 * ftp上传文件 76 * 77 * @param file 文件 78 * @param projectId 项目ID 79 * @return true||false 80 */ 81 public String upload(File file, Long projectId, String filePath) { 82 return instance.upload(FTP_HOST, FTP_PORT, USERNAME, PASSWORD, file, projectId, filePath); 83 } 84 85 /** 86 * 上传文件 87 * 88 * @param host ftp服务器地址 89 * @param port ftp端口 90 * @param username ftp用户 91 * @param password ftp密码 92 * @param file 文件 93 * @param projectId 项目ID 94 * @param targetPath 文件存放目录 95 * @return true||false 96 */ 97 public String upload(String host, Integer port, String username, String password, 98 File file, Long projectId, String targetPath) { 99 instance.initClient(host, port, username, password); 100 if (Objects.isNull(ftpClient) || Objects.isNull(file)) { 101 return null; 102 } 103 String filePath = getFilePath(projectId, targetPath); 104 StringBuilder sb = new StringBuilder(); 105 try (FileInputStream fis = new FileInputStream(file)) { 106 // ----- 切换到对应目录 107 changeDirectory(filePath.split(SEPARATOR)); 108 ftpClient.setBufferSize(1024); 109 ftpClient.setControlEncoding("GBK"); 110 // ----- 设置文件类型 111 ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 112 // ----- 上传 113 if (!ftpClient.storeFile(file.getName(), fis)) { 114 log.error(" ----- upload file failed, projectId: {}, file: {}", projectId, file.getName()); 115 return null; 116 } else { 117 sb.append(filePath).append(SEPARATOR).append(file.getName()); 118 log.info(" ----- upload file success, file: {}", sb.toString()); 119 } 120 } catch (Exception e) { 121 log.error(" ----- upload file failed, ", e); 122 } finally { 123 instance.close(); 124 } 125 return sb.toString(); 126 } 127 128 /** 129 * 删除ftp上的文件 130 * 131 * @param target 资源文件 132 * @return true || false 133 */ 134 public boolean remove(String target) { 135 return instance.remove(FTP_HOST, FTP_PORT, USERNAME, PASSWORD, target); 136 } 137 138 /** 139 * 删除ftp上的文件 140 * 141 * @param host ftp服务器地址 142 * @param port ftp端口 143 * @param username ftp用户 144 * @param password ftp密码 145 * @param target 资源文件 146 * @return true || false 147 */ 148 public boolean remove(String host, Integer port, String username, String password, String target) { 149 instance.initClient(host, port, username, password); 150 if (Objects.isNull(ftpClient) || StringUtils.isBlank(target)) { 151 return false; 152 } 153 boolean flag = false; 154 try { 155 changeDirectory(splitFtpFilePath(target)); 156 flag = ftpClient.deleteFile(target.substring(target.lastIndexOf(SEPARATOR) + 1)); 157 log.info(" ----- remove file {}, file: {}", flag ? "success" : "failed", target); 158 } catch (Exception e) { 159 log.error(" ----- remove file failed, ", e); 160 } finally { 161 instance.close(); 162 } 163 return flag; 164 } 165 166 /** 167 * @param filePath 资源路径 168 * @param targetPath 目标路径 169 * @return 文件 170 */ 171 public File download(String filePath, String targetPath) { 172 return download(FTP_HOST, FTP_PORT, USERNAME, PASSWORD, filePath, targetPath); 173 } 174 175 /** 176 * @param host ftp服务器地址 177 * @param port ftp端口 178 * @param username ftp用户 179 * @param password ftp密码 180 * @param filePath 资源路径 181 * @param targetPath 目标路径 182 * @return 文件 183 */ 184 public File download(String host, Integer port, String username, String password, String filePath, String targetPath) { 185 instance.initClient(host, port, username, password); 186 if (Objects.isNull(ftpClient) || StringUtils.isBlank(filePath)) { 187 return null; 188 } 189 File file = null; 190 try { 191 // ----- 切换到对应目录 192 changeDirectory(splitFtpFilePath(filePath)); 193 // ----- 获取文件名和文件 194 String fileName = filePath.substring(filePath.lastIndexOf(SEPARATOR) + 1); 195 FTPFile ftpFile = ftpClient.mdtmFile(fileName); 196 if (Objects.nonNull(ftpFile)) { 197 file = new File(targetPath + SEPARATOR + fileName); 198 // ----- 下载 199 try (OutputStream out = new FileOutputStream(file)) { 200 ftpClient.retrieveFile(fileName, out); 201 } 202 } 203 log.info(" ----- download file {}, filePath: {}, targetPath: {}", file != null ? "success" : "failed", filePath, targetPath); 204 } catch (Exception e) { 205 log.error(" ----- download file failed, ", e); 206 } finally { 207 instance.close(); 208 } 209 return file; 210 } 211 212 /** 213 * 释放资源 214 * 215 * @author tangw 2010-12-26 216 */ 217 public void close() { 218 if (Objects.isNull(ftpClient)) { 219 return; 220 } 221 if (ftpClient.isConnected()) { 222 try { 223 ftpClient.logout(); 224 ftpClient.disconnect(); 225 } catch (IOException e) { 226 log.error(" ----- close ftp server failed, ", e); 227 } 228 } 229 } 230 231 /** 232 * 切换到对应的目录,当目录不存在时,创建目录 233 * 234 * @param filePath 文件目录 235 */ 236 private void changeDirectory(String[] filePath) throws Exception { 237 for (String path : filePath) { 238 if (StringUtils.isBlank(path) || ftpClient.changeWorkingDirectory(path)) { 239 continue; 240 } 241 ftpClient.makeDirectory(path); 242 ftpClient.changeWorkingDirectory(path); 243 } 244 } 245 246 /** 247 * 根据FTP文件地址切割出FTP文件目录 248 * 249 * @param filePath 文件地址 250 * @return 文件所在目录 251 */ 252 private String[] splitFtpFilePath(String filePath) { 253 if (StringUtils.isBlank(filePath)) { 254 throw new NullPointerException("file path is null"); 255 } 256 // ----- 去掉尾[文件名] 257 filePath = filePath.substring(0, filePath.lastIndexOf(SEPARATOR)); 258 return filePath.split(SEPARATOR); 259 } 260 261 /** 262 * 根据项目ID获取目录 263 * 264 * @param projectId 项目ID 265 * @return 目录 266 */ 267 private static String getFilePath(Long projectId, String targetPath) { 268 StringBuilder sb = new StringBuilder(); 269 targetPath = targetPath == null ? DEFAULT_PATH : targetPath; 270 LocalDate now = LocalDate.now(); 271 return sb.append(targetPath).append(SEPARATOR) 272 .append(projectId).append(SEPARATOR) 273 .append(now.getYear()).append(SEPARATOR) 274 .append(now.getMonthValue()).append(SEPARATOR) 275 .append(now.getDayOfMonth()).toString(); 276 } 277 278 public static void main(String[] args) { 279 FtpUtil instance = FtpUtil.getInstance(); 280 String filePath = "F:\document\协议文档\02 HOOLINK协议\文档\HOOLINK传输协议.docx"; 281 String targetPath = "F:\file"; 282 Long projectId = 269L; 283 String file = instance.upload(new File(filePath), projectId, DEFAULT_PATH); 284 instance.download(file, targetPath); 285 instance.remove(file); 286 } 287 288 }