正所谓工欲善其事必先利其器,熟悉了下一套流程,以此铭记。
1.FTP服务搭建
由于本人使用wondiow系统,所以针对window的童鞋们可以查看。至于windowX这里配置类似,所以不要纠结于window系统不同。经过以上操作我们可以获取到ftp的用户名,密码,以及IP地址,端口号(ps:默认端口号,搭建时可以设置)
2.FTP编码集问题
由于FTP使用编码集为ISO-8859-1,所以在中文文件夹以及文件名称上传,获取服务器文件等会出现问题。有以下2中解决方案:
1.将目录、文件转码,这样就造成跟目录、文件相关的都要转码,以至于
ftpClient.changeWorkingDirectory(new String(onepath.getBytes("GBK"),"iso-8859-1"));
ftpClient.storeFile(new String(fileName.getBytes("GBK"),"iso-8859-1"), in);
ftpClient.listFiles(new String(remotePath.getBytes("GBK"),"iso-8859-1"));
那这样岂不是很麻烦,而且每次使用都需要转码,有没有更简单的呢?有,请看第2中
2.设置相应编码集等信息
ftpClient = new FTPClient();
ftpClient.setControlEncoding("GBK");
FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT);//系统类型 这表示window系统
conf.setServerLanguageCode("zh");
ftpClient.configure(conf);
ftpClient.connect(this.ip, this.port);
这边需要注意的是顺序必须这么写
3.工具类相关
1.Jar包问题
由于本人使用maven,pom中的配置
<dependency> <groupId>commons-net</groupId> <artifactId>commons-net</artifactId> <version>3.5</version> <classifier>ftp</classifier> </dependency>
2.工具类开发
1 import org.apache.commons.net.ftp.*; 2 import org.slf4j.Logger; 3 import org.slf4j.LoggerFactory; 4 5 import java.io.*; 6 import java.util.Arrays; 7 import java.util.List; 8 9 /** 10 * FTP上传工具类 11 */ 12 public class FtpUtil { 13 private static Logger log = LoggerFactory.getLogger(FtpUtil.class); 14 private final static String FILE_SEPARATOR = System.getProperties().getProperty("file.separator"); 15 private String ip; 16 private String username; 17 private String password; 18 private int port = 21; 19 private FTPClient ftpClient = null; 20 21 public FtpUtil(String serverIP, String username, String password) { 22 this.ip = serverIP; 23 this.username = username; 24 this.password = password; 25 } 26 27 public FtpUtil(String serverIP, int port, String username, String password) { 28 this.ip = serverIP; 29 this.username = username; 30 this.password = password; 31 this.port = port; 32 } 33 34 /** 35 * 连接ftp服务器 36 */ 37 public boolean connectServer() { 38 boolean result = true; 39 try { 40 ftpClient = new FTPClient(); 41 ftpClient.setControlEncoding("GBK"); 42 FTPClientConfig conf = new FTPClientConfig(FTPClientConfig.SYST_NT); 43 conf.setServerLanguageCode("zh"); 44 ftpClient.configure(conf); 45 ftpClient.connect(this.ip, this.port); 46 ftpClient.login(this.username, this.password); 47 ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE); 48 int reply = ftpClient.getReplyCode(); 49 if (!FTPReply.isPositiveCompletion(reply)) { 50 ftpClient.disconnect(); 51 result = false; 52 } 53 } catch (IOException e) { 54 e.printStackTrace(); 55 log.error("连接ftp服务器失败", e); 56 result = false; 57 } 58 return result; 59 } 60 61 /** 62 * 断开与ftp服务器连接 63 */ 64 public boolean closeServer() { 65 try { 66 if (ftpClient != null && ftpClient.isConnected()) { 67 ftpClient.logout(); 68 ftpClient.disconnect(); 69 } 70 return true; 71 } catch (IOException e) { 72 log.error("断开与ftp服务器连接失败", e); 73 return false; 74 } 75 } 76 77 /** 78 * 向FTP根目录上传文件 79 * 80 * @param localFile 81 * @param newName 文件名称 82 * @throws Exception 83 */ 84 public boolean uploadFile(String localFile, String newName) { 85 boolean success = false; 86 InputStream input = null; 87 try { 88 File file = null; 89 if (checkFileExist(localFile)) { 90 file = new File(localFile); 91 } 92 input = new FileInputStream(file); 93 success = ftpClient.storeFile(newName, input); 94 } catch (Exception e) { 95 log.error("FTP根目录上传文件上传失败(ps:传入文件名)", e); 96 } finally { 97 if (input != null) { 98 try { 99 input.close(); 100 } catch (IOException e) { 101 e.printStackTrace(); 102 log.error("FTP根目录上传文件上传(ps:传入文件名),输入流关闭失败", e); 103 } 104 } 105 } 106 return success; 107 } 108 109 /** 110 * 向FTP根目录上传文件 111 * 112 * @param input 113 * @param newName 新文件名 114 * @throws Exception 115 */ 116 public boolean uploadFile(InputStream input, String newName) { 117 boolean success = false; 118 try { 119 success = ftpClient.storeFile(newName, input); 120 } catch (Exception e) { 121 log.error("FTP根目录上传文件上传失败(ps:传入文件流)", e); 122 } finally { 123 if (input != null) { 124 try { 125 input.close(); 126 } catch (IOException e) { 127 e.printStackTrace(); 128 log.error("FTP根目录上传文件上传(ps:传入文件流),输入流关闭失败", e); 129 } 130 } 131 } 132 return success; 133 } 134 135 /** 136 * 向FTP指定路径上传文件 137 * 138 * @param localFile 139 * @param newName 新文件名 140 * @param remoteFoldPath 141 * @throws Exception 142 */ 143 public boolean uploadFile(String localFile, String newName, String remoteFoldPath) { 144 InputStream input = null; 145 boolean success = false; 146 try { 147 // 改变当前路径到指定路径 148 if (!this.changeDirectory(remoteFoldPath)) { 149 return false; 150 } 151 File file = null; 152 if (checkFileExist(localFile)) { 153 file = new File(localFile); 154 } 155 input = new FileInputStream(file); 156 success = ftpClient.storeFile(newName, input); 157 } catch (Exception e) { 158 log.error("FTP指定路径上传文件失败(ps:本地文件路径以及ftp服务器中文件名)", e); 159 } finally { 160 if (input != null) { 161 try { 162 input.close(); 163 } catch (IOException e) { 164 e.printStackTrace(); 165 log.error("FTP指定路径上传文件失败(ps:本地文件路径以及ftp服务器中文件名),输入流关闭失败", e); 166 } 167 } 168 } 169 return success; 170 } 171 172 /** 173 * 向FTP指定路径上传文件 174 * 175 * @param input 176 * @param newName 新文件名 177 * @param remoteFoldPath 178 * @throws Exception 179 */ 180 public boolean uploadFile(InputStream input, String newName, String remoteFoldPath) throws Exception { 181 boolean success = false; 182 try { 183 // 改变当前路径到指定路径 184 if (!this.changeDirectory(remoteFoldPath)) { 185 return false; 186 } 187 success = ftpClient.storeFile(newName, input); 188 } catch (Exception e) { 189 log.error("FTP指定路径上传文件失败(ps:本地文件流及ftp服务器中文件名)", e); 190 } finally { 191 if (input != null) { 192 try { 193 input.close(); 194 } catch (IOException e) { 195 log.error("FTP指定路径上传文件失败(ps:本地文件流及ftp服务器中文件名),输入流关闭失败", e); 196 } 197 } 198 } 199 return success; 200 } 201 202 /** 203 * 从FTP服务器下载文件 204 * 205 * @param remotePath FTP路径(不包含文件名) 206 * @param fileName 下载文件名 207 * @param localPath 本地路径 208 */ 209 public boolean downloadFile(String remotePath, String fileName, String localPath) { 210 BufferedOutputStream output = null; 211 boolean success = false; 212 try { 213 // 检查本地路径 214 if (!this.checkFileExist(localPath)) { 215 return false; 216 } 217 // 改变工作路径 218 if (!this.changeDirectory(remotePath)) { 219 return false; 220 } 221 // 列出当前工作路径下的文件列表 222 List<FTPFile> fileList = this.getFileList(); 223 if (fileList == null || fileList.size() == 0) { 224 return false; 225 } 226 for (FTPFile ftpfile : fileList) { 227 if (ftpfile.getName().equals(fileName)) { 228 File localFilePath = new File(localPath + File.separator + ftpfile.getName()); 229 output = new BufferedOutputStream(new FileOutputStream(localFilePath)); 230 success = ftpClient.retrieveFile(ftpfile.getName(), output); 231 } 232 } 233 } catch (Exception e) { 234 log.error("FTP服务器下载文件失败", e); 235 } finally { 236 if (output != null) { 237 try { 238 output.close(); 239 } catch (IOException e) { 240 log.error("FTP服务器下载文件,输出流关闭失败", e); 241 } 242 } 243 } 244 return success; 245 } 246 247 /** 248 * 从FTP服务器获取文件流 249 * 250 * @param remoteFilePath 251 * @return 252 * @throws Exception 253 */ 254 public InputStream downloadFile(String remoteFilePath) { 255 try { 256 return ftpClient.retrieveFileStream(remoteFilePath); 257 } catch (IOException e) { 258 log.error("FTP服务器获取文件流失败", e); 259 } 260 return null; 261 } 262 263 /** 264 * 获取FTP服务器上[指定路径]下的文件列表 265 * 266 * @param remotePath 267 * @return 268 */ 269 public List<FTPFile> getFtpServerFileList(String remotePath) { 270 try { 271 FTPListParseEngine engine = ftpClient.initiateListParsing(remotePath); 272 return Arrays.asList(engine.getNext(25)); 273 } catch (IOException e) { 274 log.error("获取FTP服务器上[指定路径]下的文件列表(getFtpServerFileList)失败", e); 275 } 276 return null; 277 } 278 279 /** 280 * 获取FTP服务器上[指定路径]下的文件列表 281 * 282 * @param remotePath 283 * @return 284 */ 285 public List<FTPFile> getFileList(String remotePath) { 286 List<FTPFile> ftpfiles = null; 287 try { 288 ftpfiles = Arrays.asList(ftpClient.listFiles(remotePath)); 289 } catch (IOException e) { 290 log.error("获取FTP服务器上[指定路径]下的文件列表(getFileList)失败", e); 291 } 292 return ftpfiles; 293 } 294 295 /** 296 * 获取FTP服务器[当前工作路径]下的文件列表 297 * 298 * @return 299 */ 300 public List<FTPFile> getFileList() { 301 List<FTPFile> ftpfiles = null; 302 try { 303 ftpfiles = Arrays.asList(ftpClient.listFiles()); 304 } catch (IOException e) { 305 log.error("获取FTP服务器[当前工作路径]下的文件列表失败", e); 306 } 307 return ftpfiles; 308 } 309 310 /** 311 * 改变FTP服务器工作路径 312 * 313 * @param remoteFoldPath 314 */ 315 public boolean changeDirectory(String remoteFoldPath) { 316 boolean result = false; 317 try { 318 result = ftpClient.changeWorkingDirectory(new String(remoteFoldPath)); 319 } catch (IOException e) { 320 log.error("改变FTP服务器工作路径失败", e); 321 } 322 return result; 323 } 324 325 /** 326 * 删除文件 327 * 328 * @param remoteFilePath 329 * @return 330 * @throws Exception 331 */ 332 public boolean deleteFtpServerFile(String remoteFilePath) { 333 boolean result = false; 334 try { 335 result = ftpClient.deleteFile(remoteFilePath); 336 } catch (IOException e) { 337 log.error("FTP服务器删除文件失败", e); 338 } 339 return result; 340 } 341 342 /** 343 * 删除目录 344 * 345 * @param remoteFoldPath 346 * @return 347 * @throws Exception 348 */ 349 public boolean deleteFold(String remoteFoldPath) { 350 boolean result = false; 351 try { 352 result = ftpClient.removeDirectory(remoteFoldPath); 353 } catch (IOException e) { 354 log.error("FTP服务器删除目录失败", e); 355 } 356 return result; 357 } 358 359 /** 360 * 删除目录以及文件 361 * 362 * @param remoteFoldPath 363 * @return 364 */ 365 public boolean deleteFoldAndsubFiles(String remoteFoldPath) { 366 boolean success = false; 367 List<FTPFile> list = this.getFileList(remoteFoldPath); 368 if (list == null || list.size() == 0) { 369 return deleteFold(remoteFoldPath); 370 } 371 for (FTPFile ftpFile : list) { 372 String name = ftpFile.getName(); 373 if (ftpFile.isDirectory()) { 374 success = deleteFoldAndsubFiles(remoteFoldPath + FILE_SEPARATOR + name); 375 } else { 376 success = deleteFtpServerFile(remoteFoldPath + FILE_SEPARATOR + name); 377 } 378 if (!success) { 379 break; 380 } 381 } 382 if (!success) { 383 return false; 384 } 385 success = deleteFold(remoteFoldPath); 386 return success; 387 } 388 389 /** 390 * 创建目录 391 * 392 * @param remoteFoldPath 393 * @return 394 */ 395 public boolean createFold(String remoteFoldPath) { 396 boolean result = false; 397 try { 398 result = ftpClient.makeDirectory(remoteFoldPath); 399 } catch (IOException e) { 400 log.error("FTP服务器创建目录失败", e); 401 } 402 return result; 403 } 404 405 406 /** 407 * 检查本地路径是否存在 408 * 409 * @param filePath 410 * @return 411 * @throws Exception 412 */ 413 public boolean checkFileExist(String filePath) { 414 return new File(filePath).exists(); 415 } 416 417 /** 418 * 把文件移动到特定目录下 419 * 420 * @param remoteFile 421 * @param remoteNewPath 422 * @return 423 */ 424 public boolean moveFtpServerFile(String remoteFile, String remoteNewPath) { 425 boolean result = false; 426 try { 427 result = ftpClient.rename(remoteFile, remoteNewPath); 428 } catch (IOException e) { 429 log.error("FTP服务器文件移动失败", e); 430 } 431 return result; 432 } 433 434 /** 435 * 判断是文件还是目录 436 * 437 * @param remoteOldPath 438 * @return 439 */ 440 public boolean isContents(String remoteOldPath) { 441 return changeDirectory(remoteOldPath); 442 } 443 444 /** 445 * 递归创建远程服务器目录 446 * 447 * @param dirpath 远程服务器文件绝对路径 448 * @return 目录创建是否成功 449 */ 450 public void createDirecroty(String dirpath) { 451 String directory = dirpath.substring(0, dirpath.lastIndexOf("/") + 1); 452 try { 453 if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(new String(directory))) { 454 // 如果远程目录不存在,则递归创建远程服务器目录 455 int start = 0; 456 int end = 0; 457 if (directory.startsWith("/")) { 458 start = 1; 459 } else { 460 start = 0; 461 } 462 end = directory.indexOf("/", start); 463 while (true) { 464 String subDirectory = new String(dirpath.substring(start, end)); 465 if (!ftpClient.changeWorkingDirectory(subDirectory)) { 466 if (ftpClient.makeDirectory(subDirectory)) { 467 ftpClient.changeWorkingDirectory(subDirectory); 468 } 469 } 470 start = end + 1; 471 end = directory.indexOf("/", start); 472 // 检查所有目录是否创建完毕 473 if (end <= start) { 474 break; 475 } 476 } 477 } 478 } catch (IOException e) { 479 log.error("递归生成目录失败", e); 480 } 481 } 482 483 484 /** 485 * 复制 486 * 487 * @param remoteOldPath 488 * @param remoteNewPath 489 * @return 490 */ 491 public boolean copyFtpServerFile(String remoteOldPath, String remoteNewPath) { 492 boolean copyFalg = false; 493 List<FTPFile> filelist; 494 try { 495 ftpClient.enterLocalPassiveMode(); 496 filelist = this.getFileList(remoteOldPath); 497 int length = filelist == null || filelist.isEmpty() ? 0 : filelist.size(); 498 String category = null; 499 ByteArrayOutputStream fos = null; 500 ByteArrayInputStream in = null; 501 if (length > 0) { 502 boolean flage = false; 503 if (this.isContents(remoteOldPath)) { 504 flage = true; 505 } 506 changeDirectory("/"); 507 for (FTPFile ftpFile : filelist) { 508 category = ftpFile.getName(); 509 if (ftpFile.isFile()) { 510 // 如果是文件则复制文件 511 ftpClient.setBufferSize(1024); 512 fos = new ByteArrayOutputStream(); 513 copyFalg = ftpClient.retrieveFile(flage ? remoteOldPath + FILE_SEPARATOR + category : remoteOldPath, fos); 514 if (!copyFalg) { 515 return copyFalg; 516 } 517 // 如果读取的文件流不为空则复制文件 518 if (fos != null) { 519 in = new ByteArrayInputStream(fos.toByteArray()); 520 copyFalg = ftpClient.storeFile(remoteNewPath + FILE_SEPARATOR + category, in); 521 // 关闭文件流 522 fos.close(); 523 in.close(); 524 if (!copyFalg) { 525 return copyFalg; 526 } 527 } 528 } else if (ftpFile.isDirectory()) { 529 // 如果是目录则先创建该目录 530 copyFalg = this.createFold(remoteNewPath + FILE_SEPARATOR + category); 531 // 再进入子目录进行递归复制 532 copyFtpServerFile(remoteOldPath + FILE_SEPARATOR + category, remoteNewPath + FILE_SEPARATOR + category); 533 } 534 } 535 } 536 } catch (IOException e) { 537 log.error("文件复制失败", e); 538 copyFalg = false; 539 } 540 return copyFalg; 541 } 542 543 public static void main(String[] args) { 544 FtpUtil ftpUtil = new FtpUtil("", "", ""); 545 //执行文件移动 546 /*if (ftpUtil.connectServer()) { 547 if (ftpUtil.changeDirectory("load")) { 548 ftpUtil.moveFtpServerFile("xlsj_h1_v0.7.apk", ".." + FILE_SEPARATOR + "down" + FILE_SEPARATOR + "1.apk"); 549 ftpUtil.closeServer(); 550 } 551 }*/ 552 //复制 xlsj_h1_v0.8.apk是目录 xlsj_h1_v0.7.apk是文件 553 /* if (ftpUtil.connectServer()) { 554 ftpUtil.copyFtpServerFile("load/xlsj_h1_v0.8.apk", "down"); 555 ftpUtil.copyFtpServerFile("load/xlsj_h1_v0.8.apk/xlsj_h1_v0.7.apk", "down"); 556 ftpUtil.closeServer(); 557 }*/ 558 559 if (ftpUtil.connectServer()) { 560 ftpUtil.copyFtpServerFile("load/安卓上传包/安卓开发包.apk", "down"); 561 ftpUtil.closeServer(); 562 } 563 } 564 }
参考:
http://blog.csdn.net/iheng_scau/article/details/41682511
http://blog.163.com/biangji_and/blog/static/3382923020102491050525/
http://bbs.csdn.net/topics/390373219
http://commons.apache.org/proper/commons-net/javadocs/api-1.4.1/org/apache/commons/net/ftp/FTPClient.html
http://yangyangmyself.iteye.com/blog/1299997