关键词搜索

源码搜索 ×
×

Apache FTP多线程文件上传、下载、修改文件名、删除

发布2014-04-24浏览6221次

详情内容

请参考上一篇章:Apache FTP文件上传、下载、修改文件名、删除

此处实现多线程对FTP文件的操作,FTPStatus来自上一篇文章,下附工具代码。

  1. package com.scengine.wtms.utils.ftp;
  2. import java.io.File;
  3. import java.io.FileInputStream;
  4. import java.io.FileOutputStream;
  5. import java.io.IOException;
  6. import java.io.InputStream;
  7. import java.io.OutputStream;
  8. import java.io.PrintWriter;
  9. import java.net.SocketException;
  10. import javax.servlet.http.HttpServletResponse;
  11. import org.apache.commons.net.PrintCommandListener;
  12. import org.apache.commons.net.ftp.FTP;
  13. import org.apache.commons.net.ftp.FTPClient;
  14. import org.apache.commons.net.ftp.FTPFile;
  15. import org.apache.commons.net.ftp.FTPReply;
  16. import com.scengine.wtms.utils.Log;
  17. public class ThreadFTPUtils implements Runnable
  18. {
  19. private UserInfo userInfo;
  20. private FTPClient ftpClient = new FTPClient();
  21. private FTPType ftpType;
  22. public FTPType getFtpType()
  23. {
  24. return ftpType;
  25. }
  26. public void setFtpType(FTPType ftpType)
  27. {
  28. this.ftpType = ftpType;
  29. }
  30. public static enum FTPType{
  31. UPLOAD(0),DOWNLOAD(1),RENAME(2),DELETE(3);
  32. private int type;
  33. public int getType()
  34. {
  35. return type;
  36. }
  37. public void setType(int type)
  38. {
  39. this.type = type;
  40. }
  41. FTPType(int type){
  42. this.type=type;
  43. }
  44. }
  45. /**
  46. * 对象构造 设置将过程中使用到的命令输出到控制台
  47. */
  48. public ThreadFTPUtils(String ip,int port,String username,String password,String local,String remote,FTPType ftpType)
  49. {
  50. userInfo=new UserInfo(ip, port, username, password, local, remote);
  51. this.ftpType=ftpType;
  52. this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out)));
  53. }
  54. /**
  55. *
  56. * java编程中用于连接到FTP服务器
  57. *
  58. * @param hostname
  59. * 主机名
  60. *
  61. * @param port
  62. * 端口
  63. *
  64. * @param username
  65. * 用户名
  66. *
  67. * @param password
  68. * 密码
  69. *
  70. * @return 是否连接成功
  71. *
  72. * @throws IOException
  73. */
  74. public boolean connect(String hostname, int port, String username, String password) throws IOException
  75. {
  76. ftpClient.connect(hostname, port);
  77. if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode()))
  78. {
  79. if (ftpClient.login(username, password))
  80. {
  81. return true;
  82. }
  83. }
  84. disconnect();
  85. return false;
  86. }
  87. /**
  88. * 删除远程FTP文件
  89. *
  90. * @param remote
  91. * 远程文件路径
  92. * @return
  93. * @throws IOException
  94. */
  95. public FTPStatus delete(String remote) throws IOException
  96. {
  97. ftpClient.enterLocalPassiveMode();
  98. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  99. FTPStatus result = null;
  100. FTPFile[] files = ftpClient.listFiles(remote);
  101. if (files.length == 1)
  102. {
  103. boolean status = ftpClient.deleteFile(remote);
  104. result = status ? FTPStatus.Delete_Remote_Success : FTPStatus.Delete_Remote_Faild;
  105. }
  106. else
  107. {
  108. result = FTPStatus.Not_Exist_File;
  109. }
  110. Log.getLogger(this.getClass()).info("FTP服务器文件删除标识:"+result);
  111. return result;
  112. }
  113. /**
  114. * 重命名远程FTP文件
  115. *
  116. * @param name
  117. * 新远程文件名称(路径-必须保证在同一路径下)
  118. *
  119. * @param remote
  120. * 远程文件路径
  121. *
  122. * @return 是否成功
  123. *
  124. * @throws IOException
  125. */
  126. public FTPStatus rename(String name,String remote) throws IOException
  127. {
  128. ftpClient.enterLocalPassiveMode();
  129. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  130. FTPStatus result = null;
  131. FTPFile[] files = ftpClient.listFiles(remote);
  132. if (files.length == 1)
  133. {
  134. boolean status = ftpClient.rename(remote, name);
  135. result = status ? FTPStatus.Remote_Rename_Success : FTPStatus.Remote_Rename_Faild;
  136. }
  137. else
  138. {
  139. result = FTPStatus.Not_Exist_File;
  140. }
  141. Log.getLogger(this.getClass()).info("FTP服务器文件名更新标识:"+result);
  142. return result;
  143. }
  144. /**
  145. *
  146. * 从FTP服务器上下载文件
  147. *
  148. * @param fileName
  149. * 下载文件的名字(包括后缀名)
  150. *
  151. * @param remote
  152. * 远程文件路径
  153. *
  154. * @param local
  155. * 本地文件路径
  156. *
  157. * @return 是否成功
  158. *
  159. * @throws IOException
  160. */
  161. public FTPStatus download(String fileName,String remote,HttpServletResponse response) throws IOException
  162. {
  163. // 开启输出流弹出文件保存路径选择窗口
  164. response.setContentType("application/octet-stream");
  165. response.setContentType("application/OCTET-STREAM;charset=UTF-8");
  166. response.setHeader("Content-Disposition", "attachment;filename=" +fileName);
  167. ftpClient.enterLocalPassiveMode();
  168. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  169. FTPStatus result;
  170. OutputStream out = response.getOutputStream();
  171. boolean status = ftpClient.retrieveFile(remote, out);
  172. result=status?FTPStatus.Download_From_Break_Success:FTPStatus.Download_From_Break_Faild;
  173. Log.getLogger(this.getClass()).info("FTP服务器文件下载标识:"+result);
  174. out.close();
  175. return result;
  176. }
  177. /**
  178. *
  179. * 从FTP服务器上下载文件
  180. *
  181. * @param remote
  182. * 远程文件路径
  183. *
  184. * @param local
  185. * 本地文件路径
  186. *
  187. * @return 是否成功
  188. *
  189. * @throws IOException
  190. */
  191. @SuppressWarnings("resource")
  192. public FTPStatus download(String remote, String local) throws IOException
  193. {
  194. ftpClient.enterLocalPassiveMode();
  195. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  196. FTPStatus result;
  197. File f = new File(local);
  198. FTPFile[] files = ftpClient.listFiles(remote);
  199. if (files.length != 1)
  200. {
  201. Log.getLogger(this.getClass()).info("远程文件不唯一");
  202. return FTPStatus.File_Not_Unique;
  203. }
  204. long lRemoteSize = files[0].getSize();
  205. if (f.exists())
  206. {
  207. OutputStream out = new FileOutputStream(f, true);
  208. Log.getLogger(this.getClass()).info("本地文件大小为:" + f.length());
  209. if (f.length() >= lRemoteSize)
  210. {
  211. Log.getLogger(this.getClass()).info("本地文件大小大于远程文件大小,下载中止");
  212. return FTPStatus.Remote_smaller_local;
  213. }
  214. ftpClient.setRestartOffset(f.length());
  215. boolean status = ftpClient.retrieveFile(remote, out);
  216. result=status?FTPStatus.Download_From_Break_Success:FTPStatus.Download_From_Break_Faild;
  217. out.close();
  218. } else
  219. {
  220. OutputStream out = new FileOutputStream(f);
  221. boolean status = ftpClient.retrieveFile(remote, out);
  222. result=status?FTPStatus.Download_From_Break_Success:FTPStatus.Download_From_Break_Faild;
  223. out.close();
  224. }
  225. return result;
  226. }
  227. /**
  228. *
  229. * 上传文件到FTP服务器,支持断点续传
  230. *
  231. * @param local
  232. * 本地文件名称,绝对路径
  233. *
  234. * @param remote
  235. * 远程文件路径,使用/home/directory1/subdirectory/file.ext
  236. * 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
  237. *
  238. * @return 上传结果
  239. *
  240. * @throws IOException
  241. */
  242. @SuppressWarnings("resource")
  243. public FTPStatus upload(String local, String remote) throws IOException
  244. {
  245. // 设置PassiveMode传输
  246. ftpClient.enterLocalPassiveMode();
  247. // 设置以二进制流的方式传输
  248. ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
  249. FTPStatus result;
  250. // 对远程目录的处理
  251. String remoteFileName = remote;
  252. if (remote.contains("/"))
  253. {
  254. remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);
  255. String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
  256. if (!directory.equalsIgnoreCase("/") && !ftpClient.changeWorkingDirectory(directory))
  257. {
  258. // 如果远程目录不存在,则递归创建远程服务器目录
  259. int start = 0;
  260. int end = 0;
  261. if (directory.startsWith("/"))
  262. {
  263. start = 1;
  264. } else
  265. {
  266. start = 0;
  267. }
  268. end = directory.indexOf("/", start);
  269. while (true)
  270. {
  271. String subDirectory = remote.substring(start, end);
  272. if (!ftpClient.changeWorkingDirectory(subDirectory))
  273. {
  274. if (ftpClient.makeDirectory(subDirectory))
  275. {
  276. ftpClient.changeWorkingDirectory(subDirectory);
  277. } else
  278. {
  279. Log.getLogger(this.getClass()).info("创建目录失败");
  280. return FTPStatus.Create_Directory_Fail;
  281. }
  282. }
  283. start = end + 1;
  284. end = directory.indexOf("/", start);
  285. // 检查所有目录是否创建完毕
  286. if (end <= start)
  287. {
  288. break;
  289. }
  290. }
  291. }
  292. }
  293. // 检查远程是否存在文件
  294. FTPFile[] files = ftpClient.listFiles(remoteFileName);
  295. if (files.length == 1)
  296. {
  297. long remoteSize = files[0].getSize();
  298. File f = new File(local);
  299. long localSize = f.length();
  300. if (remoteSize == localSize)
  301. {
  302. return FTPStatus.File_Exits;
  303. } else if (remoteSize > localSize)
  304. {
  305. return FTPStatus.Remote_Bigger_Local;
  306. }
  307. // 尝试移动文件内读取指针,实现断点续传
  308. InputStream is = new FileInputStream(f);
  309. if (is.skip(remoteSize) == remoteSize)
  310. {
  311. ftpClient.setRestartOffset(remoteSize);
  312. if (ftpClient.storeFile(remote, is))
  313. {
  314. return FTPStatus.Upload_From_Break_Success;
  315. }
  316. }
  317. // 如果断点续传没有成功,则删除服务器上文件,重新上传
  318. if (!ftpClient.deleteFile(remoteFileName))
  319. {
  320. return FTPStatus.Delete_Remote_Faild;
  321. }
  322. is = new FileInputStream(f);
  323. if (ftpClient.storeFile(remote, is))
  324. {
  325. result = FTPStatus.Upload_New_File_Success;
  326. } else
  327. {
  328. result = FTPStatus.Upload_New_File_Failed;
  329. }
  330. is.close();
  331. } else
  332. {
  333. InputStream is = new FileInputStream(local);
  334. if (ftpClient.storeFile(remoteFileName, is))
  335. {
  336. result = FTPStatus.Upload_New_File_Success;
  337. } else
  338. {
  339. result = FTPStatus.Upload_New_File_Failed;
  340. }
  341. is.close();
  342. }
  343. return result;
  344. }
  345. /**
  346. *
  347. * 断开与远程服务器的连接
  348. *
  349. * @throws IOException
  350. */
  351. public void disconnect() throws IOException
  352. {
  353. if (ftpClient.isConnected())
  354. {
  355. ftpClient.disconnect();
  356. }
  357. }
  358. @Override
  359. public void run()
  360. {
  361. boolean status=false;
  362. // 建立FTP连接
  363. try
  364. {
  365. ftpClient.connect(userInfo.getIp(), userInfo.getPort());
  366. if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode()))
  367. {
  368. if (ftpClient.login(userInfo.getUsername(), userInfo.getPassword()))
  369. {
  370. status=true;
  371. }
  372. }else{
  373. try
  374. {
  375. disconnect();
  376. } catch (IOException e)
  377. {
  378. e.printStackTrace();
  379. }
  380. }
  381. } catch (SocketException e1)
  382. {
  383. e1.printStackTrace();
  384. } catch (IOException e1)
  385. {
  386. e1.printStackTrace();
  387. }
  388. // FTP连接成功后执行相应的操作
  389. if(status){
  390. FTPStatus result=null;
  391. if(this.ftpType==FTPType.UPLOAD)
  392. {
  393. try
  394. {
  395. result=this.upload(userInfo.getLocal(), userInfo.getRemote());// 上传文件
  396. } catch (IOException e)
  397. {
  398. Log.getLogger(ThreadFTPUtils.class).info("FTP上传文件异常:" + e.getMessage());
  399. }
  400. }else if(this.ftpType==FTPType.DOWNLOAD)
  401. {
  402. try
  403. {
  404. result=this.download(userInfo.getRemote(), userInfo.getLocal());// 下载文件
  405. } catch (IOException e)
  406. {
  407. Log.getLogger(ThreadFTPUtils.class).info("FTP下载文件异常:" + e.getMessage());
  408. }
  409. }else if(this.ftpType==FTPType.RENAME)
  410. {
  411. try
  412. {
  413. result=this.rename(userInfo.getLocal(), userInfo.getRemote());// 修改名称
  414. } catch (IOException e)
  415. {
  416. Log.getLogger(ThreadFTPUtils.class).info("FTP修改文件名称异常:" + e.getMessage());
  417. }
  418. }else if(this.ftpType==FTPType.DELETE)
  419. {
  420. try
  421. {
  422. result=this.delete(userInfo.getRemote()); // 删除文件
  423. } catch (IOException e)
  424. {
  425. Log.getLogger(ThreadFTPUtils.class).info("FTP删除文件异常:" + e.getMessage());
  426. }
  427. }
  428. try
  429. {
  430. disconnect();
  431. } catch (IOException e)
  432. {
  433. Log.getLogger(ThreadFTPUtils.class).info("FTP连接释放异常:" + e.getMessage());
  434. }
  435. Log.getLogger(this.getClass()).info("FTP操作状态码:"+result);
  436. }
  437. }
  438. public static void main(String[] args)
  439. {
  440. ThreadFTPUtils myFtp = new ThreadFTPUtils("192.168.1.200", 21, "duser", "HTPDuserXP32","C:\\Users\\Administrator\\Desktop\\swing.drawer.jar","/jars/boonya.jar",FTPType.UPLOAD);
  441. Thread thread=new Thread(myFtp);
  442. thread.start();
  443. }
  444. }
  445. class UserInfo{
  446. private String ip; //FTP服务器的IP地址
  447. private int port; //FTP服务器端口
  448. private String username;//登录用户名
  449. private String password;//登录密码
  450. private String local; //本地文件或文件名
  451. private String remote; //远程文件或路径
  452. public String getIp()
  453. {
  454. return ip;
  455. }
  456. public void setIp(String ip)
  457. {
  458. this.ip = ip;
  459. }
  460. public int getPort()
  461. {
  462. return port;
  463. }
  464. public void setPort(int port)
  465. {
  466. this.port = port;
  467. }
  468. public String getUsername()
  469. {
  470. return username;
  471. }
  472. public void setUsername(String username)
  473. {
  474. this.username = username;
  475. }
  476. public String getPassword()
  477. {
  478. return password;
  479. }
  480. public void setPassword(String password)
  481. {
  482. this.password = password;
  483. }
  484. public String getLocal()
  485. {
  486. return local;
  487. }
  488. public void setLocal(String local)
  489. {
  490. this.local = local;
  491. }
  492. public String getRemote()
  493. {
  494. return remote;
  495. }
  496. public void setRemote(String remote)
  497. {
  498. this.remote = remote;
  499. }
  500. public UserInfo()
  501. {
  502. }
  503. public UserInfo(String ip, int port, String username, String password, String local, String remote)
  504. {
  505. this.ip = ip;
  506. this.port = port;
  507. this.username = username;
  508. this.password = password;
  509. this.local = local;
  510. this.remote = remote;
  511. }
  512. }


相关技术文章

最新源码

下载排行榜

点击QQ咨询
开通会员
返回顶部
×
微信扫码支付
微信扫码支付
确定支付下载
请使用微信描二维码支付
×

提示信息

×

选择支付方式

  • 微信支付
  • 支付宝付款
确定支付下载