1 /**
2 * @(#)FtpUtil.java
3 *
4 * @author huawei
5 * @version 1.0 2011-9-15
6 *
7 * Copyright (C) 2000,2011 , KOAL, Inc.
8 */
9 package koal.icmp.biz.common;
10
11 import java.io.File;
12 import java.io.FileInputStream;
13 import java.io.FileNotFoundException;
14 import java.io.FileOutputStream;
15 import java.io.IOException;
16 import java.io.InputStream;
17 import java.io.OutputStream;
18 import java.io.PrintWriter;
19 import java.net.SocketException;
20 import java.util.ArrayList;
21 import java.util.List;
22
23 import koal.icmp.bean.exception.EMVException;
24
25 import org.apache.commons.logging.Log;
26 import org.apache.commons.logging.LogFactory;
27 import org.apache.commons.net.PrintCommandListener;
28 import org.apache.commons.net.ftp.FTP;
29 import org.apache.commons.net.ftp.FTPClient;
30 import org.apache.commons.net.ftp.FTPClientConfig;
31 import org.apache.commons.net.ftp.FTPFile;
32 import org.apache.commons.net.ftp.FTPReply;
33
34 /**
35 *
36 * Purpose: Ftp操作客户端 apache 版
37 *
38 * @see
39 * @since 6.1.0
40 */
41 public class FtpUtil
42 {
43
44 private static final FtpUtil ftp = new FtpUtil();
45 private Log log =LogFactory.getLog(getClass());
46
47 FTPClient ftpClient;
48
49 private FtpUtil()
50 {
51
52 }
53
54 public static FtpUtil getInstance(String server, int port, String loginName, String loginPwd) throws EMVException
55 {
56 ftp.init(server, port, loginName, loginPwd);
57 return ftp;
58 }
59
60 public static FtpUtil getInstance()
61 {
62 return ftp;
63 }
64
65 public void init(String server, int port, String loginName, String loginPwd, boolean isPrintCommand) throws EMVException
66 {
67 init(null, server, port, loginName, loginPwd, isPrintCommand);
68 }
69
70 public void init(String server, int port, String loginName, String loginPwd) throws EMVException
71 {
72 init(null, server, port, loginName, loginPwd, false);
73 }
74
75 public void init(FTPClientConfig config, String server, int port, String loginName, String loginPwd, boolean isPrintCommand) throws EMVException
76 {
77 ftpClient = new FTPClient();
78 // 设置编码
79 ftpClient.setControlEncoding("utf-8");
80
81 if (config == null)
82 {
83 config = new FTPClientConfig();
84 config.setServerLanguageCode("zh");
85 }
86
87 ftpClient.configure(config);
88
89 if (isPrintCommand)
90 ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out), true));
91 try
92 {
93 ftpClient.connect(server, port);
94 if (!ftpClient.login(loginName, loginPwd))
95 throw new EMVException("登录服务器[" + server + "]失败!检查用户名或密码是否正确");
96 } catch (SocketException e)
97 {
98 throw new EMVException("连接服务器[" + server + "]失败!请检查主机名和端口是否正确", e);
99 } catch (IOException e)
100 {
101 throw new EMVException("登录服务器[" + server + "]失败!检查用户名或密码是否正确", e);
102 }
103 }
104
105 /***************************************************************************
106 * 连接是否有效的
107 *
108 * @return
109 */
110 public Boolean isPositive()
111 {
112 return FTPReply.isPositiveCompletion(ftpClient.getReplyCode());
113 }
114
115 private void isPositiveable() throws EMVException
116 {
117 if (!isPositive())
118 {
119 closeFtpConnection();
120 throw new EMVException("FTP连接已经失效,请重试!");
121 }
122 }
123
124 /***************************************************************************
125 * 下载文件
126 *
127 * @param outputStream
128 * @param remoteFileName
129 * @param fileType
130 * @throws EMVException
131 * @throws IOException
132 */
133 public boolean download(OutputStream outputStream, String remoteFileName, int fileType) throws EMVException, IOException
134 {
135 isPositiveable();
136 try
137 {
138 ftpClient.setFileType(fileType);
139 return ftpClient.retrieveFile(remoteFileName, outputStream);
140 } catch (FileNotFoundException e)
141 {
142 e.printStackTrace();
143 throw new EMVException("操作文件出现异常", e);
144 } catch (IOException e)
145 {
146 e.printStackTrace();
147 throw new EMVException("操作文件出现异常", e);
148 } finally
149 {
150 if (outputStream != null)
151 outputStream.close();
152 closeFtpConnection();
153 }
154 }
155
156 /***************************************************************************
157 * 下载文件
158 *
159 * @param outputStream
160 * @param remoteFileName
161 * @param fileType
162 * @throws EMVException
163 * @throws IOException
164 */
165 public boolean download(OutputStream outputStream, String remoteFileName) throws EMVException, IOException
166 {
167 return download(outputStream, remoteFileName, FTP.BINARY_FILE_TYPE);
168 }
169
170 /***************************************************************************
171 *
172 * @param file
173 * 下载下来的文件
174 * @param remoteFileName
175 * @throws EMVException
176 * @throws IOException
177 */
178 public boolean download(File file, String remoteFileName) throws EMVException, IOException
179 {
180 OutputStream outputStream = new FileOutputStream(file);
181 return download(outputStream, remoteFileName, FTP.BINARY_FILE_TYPE);
182 }
183
184 /***************************************************************************
185 *
186 * @param file
187 * 下载下来的文件
188 * @param remoteFileName
189 * @throws EMVException
190 * @throws IOException
191 */
192 public boolean download(String fileName, String remoteFileName) throws EMVException, IOException
193 {
194 File file = new File(fileName);
195 OutputStream outputStream = new FileOutputStream(file);
196 return download(outputStream, remoteFileName, FTP.BINARY_FILE_TYPE);
197 }
198
199 /***************************************************************************
200 * 上传文件
201 *
202 * @param InputStream
203 * @param remoteFileName
204 * @throws EMVException
205 * @throws IOException
206 */
207 public boolean upload(InputStream stream, String remoteFileName, Integer fileType) throws EMVException, IOException
208 {
209 isPositiveable();
210 try
211 {
212 ftpClient.setFileType(fileType);
213 return ftpClient.storeFile(remoteFileName, stream);
214 } catch (IOException e)
215 {
216 e.printStackTrace();
217 throw new EMVException("操作文件出现异常", e);
218 } finally
219 {
220 if (stream != null)
221 stream.close();
222 closeFtpConnection();
223 }
224 }
225 /***
226 * 切换工作目录
227 * @param pathname
228 * @return
229 * @throws EMVException
230 */
231 public boolean changeWorkingDirectory(String pathname) throws EMVException
232 {
233 try
234 {
235 return ftpClient.changeWorkingDirectory(pathname);
236 } catch (IOException e)
237 {
238 e.printStackTrace();
239 throw new EMVException("操作文件出现异常", e);
240 }
241 }
242
243 /***************************************************************************
244 * 上传文件,默认以二进制传输
245 *
246 * @param InputStream
247 * @param remoteFileName
248 * @throws EMVException
249 * @throws IOException
250 */
251 public boolean upload(InputStream stream, String remoteFileName) throws EMVException, IOException
252 {
253 return upload(stream, remoteFileName, FTP.BINARY_FILE_TYPE);
254 }
255
256 /***************************************************************************
257 * 上传文件,默认以二进制传输
258 *
259 * @param InputStream
260 * @param remoteFileName
261 * @throws EMVException
262 * @throws IOException
263 */
264 public boolean upload(File file) throws EMVException, IOException
265 {
266 InputStream inputStream = new FileInputStream(file);
267 return upload(inputStream, file.getName(), FTP.BINARY_FILE_TYPE);
268 }
269
270 /***************************************************************************
271 * 上传文件
272 *
273 * @param file
274 * @param fileType
275 * @throws EMVException
276 * @throws IOException
277 */
278 public boolean upload(File file, int fileType) throws EMVException, IOException
279 {
280 InputStream inputStream = new FileInputStream(file);
281 return upload(inputStream, file.getName(), fileType);
282 }
283
284 /***************************************************************************
285 * 列出某目录下的所有文件和文件夹
286 *
287 * @param pathName
288 * @return
289 * @throws EMVException
290 */
291 public FTPFile[] arrayFiles(String pathName) throws EMVException
292 {
293 isPositiveable();
294 try
295 {
296 return ftpClient.listFiles(pathName);
297 } catch (IOException e)
298 {
299 e.printStackTrace();
300 throw new EMVException("列出文件目录失败!", e);
301 } finally
302 {
303 closeFtpConnection();
304 }
305 }
306
307 /***************************************************************************
308 * 删除文件夹或文件,删除文件夹时,必须没有子目录或子文件
309 *
310 * @param pathName
311 * @throws EMVException
312 */
313 public boolean dele(String pathName) throws EMVException
314 {
315 isPositiveable();
316 try
317 {
318 return FTPReply.isPositiveCompletion(ftpClient.dele(pathName));
319 } catch (IOException e)
320 {
321 e.printStackTrace();
322 throw new EMVException("删除失败!", e);
323 } finally
324 {
325 closeFtpConnection();
326 }
327 }
328
329 /***************************************************************************
330 * 删除单个文件
331 *
332 * @param pathName
333 * @throws EMVException
334 */
335 public boolean delele(String pathName) throws EMVException
336 {
337 isPositiveable();
338 try
339 {
340 return ftpClient.deleteFile(pathName);
341 } catch (IOException e)
342 {
343 e.printStackTrace();
344 throw new EMVException("删除失败!", e);
345 } finally
346 {
347 closeFtpConnection();
348 }
349 }
350 /****
351 * 删除文件夹里的文件,不是会像 rm -rf 一样的
352 * @param path
353 * @return
354 * @throws EMVException
355 */
356 public boolean removeDirectory(String path) throws EMVException{
357 isPositiveable();
358 try
359 {
360 return ftpClient.removeDirectory(path);
361 } catch (IOException e)
362 {
363 e.printStackTrace();
364 throw new EMVException("删除失败!", e);
365 }
366 finally
367 {
368 closeFtpConnection();
369 }
370 }
371 /***************************************************************************
372 * 递归删除某个文件夹下的文件,但不会删除当前文件夹,需要自己关闭FTP连接
373 * @param path
374 * @return
375 * @throws EMVException
376 * @throws IOException
377 */
378 public void recursionDelele(String path) throws EMVException,IOException
379 {
380 isPositiveable();
381 FTPFile files[] = ftpClient.listFiles(path);
382 if (files == null || files.length == 0){
383 ftpClient.deleteFile(path);
384 return;
385 }
386 for (FTPFile file : files)
387 {
388 String p = path + ( file.isDirectory() ? path.endsWith("/") ? file.getName() : "/" + file.getName() + "/"
389 : path.endsWith("/") ? file.getName() : "/" + file.getName());
390 if(!file.isDirectory()){
391 ftpClient.deleteFile(p);
392 continue;
393 }
394 if (file.isDirectory())
395 recursionDelele(p);
396 }
397 }
398 /***
399 * 递归删除某个文件夹下的文件并删除当前文件夹
400 * @param path
401 * @throws IOException
402 * @throws EMVException
403 */
404 public void recursionDele(String path) throws EMVException{
405 isPositiveable();
406 FTPFile files[];
407 try
408 {
409 files = ftpClient.listFiles(path);
410 for (FTPFile file : files)
411 {
412 if(!file.isDirectory()){
413 ftpClient.deleteFile(path + "/" +file.getName());
414 continue;
415 }
416 if(file.isDirectory())
417 recursionDelele(path);
418 }
419 ftpClient.deleteFile(path);
420 } catch (IOException e)
421 {
422 e.printStackTrace();
423 throw new EMVException("文件操作失败!",e);
424 }finally{
425 closeFtpConnection();
426 }
427 }
428
429 /***
430 * 递归下载某个目录下的所有文件和文件夹,文件的命名和FTP目录的命名结构一样,不关闭FTP连接
431 * @param localDir 本地接收的目录
432 * @param remotePath
433 * @throws EMVException
434 * @throws IOException
435 */
436 private void recursionDownLoad(final String localDir,String remotePath,final String rootPath) throws EMVException, IOException{
437 isPositiveable();
438 FTPFile[] files = ftpClient.listFiles(remotePath);
439 File ff = new File(localDir + "/" +( rootPath == null ? remotePath : remotePath.substring( rootPath.length()+1,remotePath.length())));
440 if (!ff.exists())
441 ff.mkdir();
442 for (FTPFile file : files)
443 {
444 String p = remotePath+ (file.isDirectory() ? remotePath.endsWith("/") ?
445 file.getName() : "/" + file.getName() + "/" : remotePath.endsWith("/") ? file
446 .getName() : "/" + file.getName());
447 String local = rootPath == null ? localDir + "/" + p :localDir + "/" + p.substring(rootPath.length() +1,p.length());
448 if (!file.isDirectory())
449 {
450 OutputStream outputStream = new FileOutputStream(new File(local));
451 boolean b = ftpClient.retrieveFile(p, outputStream);
452 if (log.isDebugEnabled())
453 log.debug(file.getName()+" 下载 " +( b ? "成功!" : "失败!"));
454 outputStream.close();
455 }
456 if (file.isDirectory())
457 {
458 File f = new File(local);
459 if (!f.exists())
460 f.mkdir();
461 recursionDownLoad(localDir, p,rootPath);
462 }
463 }
464 }
465 /***
466 * 下载远程目录下的所有的文件和文件夹,连远程目录会一起下载
467 * @param localDir
468 * @param remotePath
469 * @throws IOException
470 * @throws EMVException
471 */
472 public void recursionDownLoad(final String localDir,String remotePath) throws EMVException, IOException{
473 try
474 {
475 recursionDownLoad(localDir,remotePath,null);
476 }catch(EMVException e){
477 throw e;
478 }catch (IOException e) {
479 throw e;
480 }
481 finally{
482 closeFtpConnection();
483 }
484 }
485
486 /***
487 * 递归下载某个目录下的所有文件和文件夹,文件的命名和FTP目录的命名结构一样不包括当前的目录,且会关闭FTP连接
488 * @param localDir 本地接收的目录
489 * @param remotePath
490 * @throws EMVException
491 * @throws IOException
492 */
493 public void recursionDownLoadAndClose(final String localDir,String remotePath) throws EMVException{
494 isPositiveable();
495 FTPFile[] files;
496 try
497 {
498 files = ftpClient.listFiles(remotePath);
499 for (FTPFile file : files)
500 {
501 String p =remotePath + (file.isDirectory() ? remotePath.endsWith("/") ?
502 file.getName() : "/" + file.getName() + "/" : remotePath.endsWith("/") ? file
503 .getName() : "/" + file.getName());
504 String local = remotePath == null ? localDir + "/" + p :localDir + "/" + p.substring(remotePath.length() +1,p.length());
505 if (!file.isDirectory())
506 {
507 OutputStream outputStream = new FileOutputStream(new File(local));
508 boolean b=ftpClient.retrieveFile(p, outputStream);
509 if (log.isDebugEnabled())
510 log.debug(file.getName()+" 下载 " +( b ? "成功!" : "失败!"));
511 outputStream.close();
512 }
513 if (file.isDirectory())
514 {
515 recursionDownLoad(localDir, p,remotePath);
516 }
517 }
518 } catch (IOException e)
519 {
520 e.printStackTrace();
521 throw new EMVException("文件操作失败!",e);
522 }finally{
523 closeFtpConnection();
524 }
525 }
526 /***
527 * 上传文件夹,下的所有文件和文件夹
528 * @param local
529 * @param remotePath
530 * @throws EMVException
531 * @throws IOException
532 */
533 private void recursionUpload(String local,final String remotePath) throws EMVException,IOException{
534 isPositiveable();
535 File file = new File(local);
536 if(!file.exists())
537 return;
538 try
539 {
540 InputStream stream =null;
541 if (file.isFile())
542 {
543 stream =new FileInputStream(file);
544 boolean b= ftpClient.storeFile(remotePath+"/" + file.getName(), stream);
545 if (log.isDebugEnabled())
546 log.debug(file.getName()+" 上传 " +( b ? "成功!" : "失败!"));
547 stream.close();
548 return ;
549 }
550 if(file.isDirectory()){
551 File [] files = file.listFiles();
552 for (int i = 0; i < files.length; i++)
553 {
554 if(files[i].isFile()){
555 stream =new FileInputStream(files[i]);
556 ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
557 boolean b = ftpClient.storeFile(remotePath+"/"+files[i].getName(), stream);
558 if (log.isDebugEnabled())
559 log.debug(files[i].getName()+" 上传 " +( b ? "成功!" : "失败!"));
560 stream.close();
561 continue;
562 }
563 if(files[i].isDirectory()){
564 ftpClient.makeDirectory(remotePath+"/"+ files[i].getName());
565 recursionUpload(files[i].getAbsolutePath(),remotePath+"/"+files[i].getName());
566 }
567
568 }
569 }
570 } catch (FileNotFoundException e)
571 {
572 throw new EMVException(local+"文件未找到!",e);
573 } catch (IOException e)
574 {
575 throw new EMVException("文件操作失败!",e);
576 }
577 }
578
579 /***
580 * 上传文件夹,下的所有文件和文件夹
581 * @param local
582 * @param remotePath
583 * @throws EMVException
584 * @throws IOException
585 */
586 public void recursionUploadFiles(String local,final String remotePath) throws EMVException, IOException{
587 try
588 {
589 recursionUpload(local,remotePath);
590 } catch (EMVException e)
591 {
592 throw e;
593 } catch (IOException e)
594 {
595 throw e;
596 }finally{
597 closeFtpConnection();
598 }
599 }
600
601 /***************************************************************************
602 * 列出pathName目录下的所有文件,排除文件夹,如果不传入路径,就会显示当前的工作空间的路径
603 *
604 * @param pathName
605 * @return
606 * @throws EMVException
607 */
608 public List<String> listFile(String pathName) throws EMVException
609 {
610 return listFiles(pathName, FTPFile.FILE_TYPE);
611 }
612
613 /***************************************************************************
614 * @param pathName
615 * @return
616 * @throws EMVException
617 */
618 public List<String> listFiles(String pathName, int fileType) throws EMVException
619 {
620 FTPFile[] files = arrayFiles(pathName);
621 List<String> fileList = new ArrayList<String>();
622 for (FTPFile file : files)
623 {
624 if (file.getType() == fileType)
625 fileList.add(file.getName());
626 }
627 return fileList;
628 }
629
630 /***************************************************************************
631 * 列出pathName目录下的所有文件,排除文件夹
632 *
633 * @param pathName
634 * @return
635 * @throws EMVException
636 */
637 public List<String> listDirectory(String pathName) throws EMVException
638 {
639 return listFiles(pathName, FTPFile.DIRECTORY_TYPE);
640 }
641
642 /***************************************************************************
643 * 移动文件
644 *
645 * @param remoteFileFrom
646 * 目标文件
647 * @param remoteFileTo
648 * 移动至
649 * @throws EMVException
650 */
651 public boolean move(String remoteFileFrom, String remoteFileTo) throws EMVException
652 {
653 isPositiveable();
654 try
655 {
656 return ftpClient.rename(remoteFileFrom, remoteFileTo);
657 } catch (IOException e)
658 {
659 e.printStackTrace();
660 throw new EMVException("远程移动文件失败!", e);
661 } finally
662 {
663 closeFtpConnection();
664 }
665 }
666
667 /***************************************************************************
668 * 创建文件夹
669 *
670 * @param remoteDirectory
671 * @throws EMVException
672 */
673 public boolean makeDirectory(String remoteDirectory) throws EMVException
674 {
675 isPositiveable();
676 try
677 {
678 return ftpClient.makeDirectory(remoteDirectory);
679 } catch (IOException e)
680 {
681 e.printStackTrace();
682 throw new EMVException("创建文件夹失败!", e);
683 } finally
684 {
685 closeFtpConnection();
686 }
687 }
688
689 /***************************************************************************
690 * 关闭FTP连接
691 *
692 * @throws EMVException
693 */
694 public void closeFtpConnection() throws EMVException
695 {
696 try
697 {
698 if (!isPositive())
699 {
700 ftpClient.logout();
701 ftpClient.disconnect();
702 }
703 } catch (IOException e)
704 {
705 e.printStackTrace();
706 throw new EMVException("关闭FTP连接出现错误!");
707 }
708 }
709
710 }
711
712 /**
713 * Revision history
714 * -------------------------------------------------------------------------
715 *
716 * Date Author Note
717 * -------------------------------------------------------------------------
718 * 2011-9-15 huawei 创建版本
719 */
720