FTP多线程,断点续传上传下载

  1 package com.hirain.ftp.thread;
  2
  3 import java.io.File;
  4 import java.io.FileOutputStream;
  5 import java.io.IOException;
  6 import java.io.InputStream;
  7 import java.io.OutputStream;
  8 import java.io.RandomAccessFile;
  9
 10 import org.apache.commons.net.ftp.FTP;
 11 import org.apache.commons.net.ftp.FTPClient;
 12 import org.apache.commons.net.ftp.FTPFile;
 13 import org.apache.commons.net.ftp.FTPReply;
 14
 15 public class FTPDownloadThread extends Thread {
 16
 17     // 枚举类UploadStatus代码
 18
 19     public enum UploadStatus {
 20         Create_Directory_Fail, // 远程服务器相应目录创建失败
 21         Create_Directory_Success, // 远程服务器闯将目录成功
 22         Upload_New_File_Success, // 上传新文件成功
 23         Upload_New_File_Failed, // 上传新文件失败
 24         File_Exits, // 文件已经存在
 25         Remote_Bigger_Local, // 远程文件大于本地文件
 26         Upload_From_Break_Success, // 断点续传成功
 27         Upload_From_Break_Failed, // 断点续传失败
 28         Delete_Remote_Faild; // 删除远程文件失败
 29     }
 30
 31     // 枚举类DownloadStatus代码
 32     public enum DownloadStatus {
 33         Remote_File_Noexist, // 远程文件不存在
 34         Local_Bigger_Remote, // 本地文件大于远程文件
 35         Download_From_Break_Success, // 断点下载文件成功
 36         Download_From_Break_Failed, // 断点下载文件失败
 37         Download_New_Success, // 全新下载文件成功
 38         Download_New_Failed; // 全新下载文件失败
 39     }
 40
 41     public FTPClient ftpClient = new FTPClient();
 42     private String ftpURL, username, pwd, ftpport, file1, file2;
 43
 44     public FTPDownloadThread(String _ftpURL, String _username, String _pwd,
 45             String _ftpport, String _file1, String _file2) {
 46         // 设置将过程中使用到的命令输出到控制台
 47         ftpURL = _ftpURL;
 48         username = _username;
 49         pwd = _pwd;
 50         ftpport = _ftpport;
 51         file1 = _file1;
 52         file2 = _file2;
 53     }
 54
 55     /**
 56      * 连接到FTP服务器
 57      *
 58      * @param hostname
 59      *            主机名
 60      * @param port
 61      *            端口
 62      * @param username
 63      *            用户名
 64      * @param password
 65      *            密码
 66      * @return 是否连接成功
 67      * @throws IOException
 68      */
 69     public boolean connect(String hostname, int port, String username,
 70             String password) throws IOException {
 71         ftpClient.connect(hostname, port);
 72         ftpClient.setControlEncoding("GBK");
 73         if (FTPReply.isPositiveCompletion(ftpClient.getReplyCode())) {
 74             if (ftpClient.login(username, password)) {
 75                 return true;
 76             }
 77         }
 78         disconnect();
 79         return false;
 80     }
 81
 82     /**
 83      * 从FTP服务器上下载文件,支持断点续传,上传百分比汇报
 84      *
 85      * @param remote
 86      *            远程文件路径
 87      * @param local
 88      *            本地文件路径
 89      * @return 上传的状态
 90      * @throws IOException
 91      */
 92     public DownloadStatus download(String remote, String local)
 93             throws IOException {
 94         // 设置被动模式
 95         ftpClient.enterLocalPassiveMode();
 96         // 设置以二进制方式传输
 97         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
 98         DownloadStatus result;
 99
100         // 检查远程文件是否存在
101         FTPFile[] files = ftpClient.listFiles(new String(
102                 remote.getBytes("GBK"), "iso-8859-1"));
103         if (files.length != 1) {
104             System.out.println("远程文件不存在");
105             return DownloadStatus.Remote_File_Noexist;
106         }
107
108         long remoteSize = files[0].getSize();
109         File f = new File(local);
110         // 本地存在文件,进行断点下载
111         if (f.exists()) {
112             long localSize = f.length();
113             // 判断本地文件大小是否大于远程文件大小
114             if (localSize >= remoteSize) {
115                 System.out.println("本地文件大于远程文件,下载中止");
116                 return DownloadStatus.Local_Bigger_Remote;
117             }
118
119             // 进行断点续传,并记录状态
120             FileOutputStream out = new FileOutputStream(f, true);
121             ftpClient.setRestartOffset(localSize);
122             InputStream in = ftpClient.retrieveFileStream(new String(remote
123                     .getBytes("GBK"), "iso-8859-1"));
124             byte[] bytes = new byte[1024];
125             long step = remoteSize / 100;
126             long process = localSize / step;
127             int c;
128             while ((c = in.read(bytes)) != -1) {
129                 out.write(bytes, 0, c);
130                 localSize += c;
131                 long nowProcess = localSize / step;
132                 if (nowProcess > process) {
133                     process = nowProcess;
134                     if (process % 10 == 0)
135                         System.out.println("下载进度:" + process);
136                     // TODO 更新文件下载进度,值存放在process变量中
137                 }
138             }
139             in.close();
140             out.close();
141             boolean isDo = ftpClient.completePendingCommand();
142             if (isDo) {
143                 result = DownloadStatus.Download_From_Break_Success;
144             } else {
145                 result = DownloadStatus.Download_From_Break_Failed;
146             }
147         } else {
148             OutputStream out = new FileOutputStream(f);
149             InputStream in = ftpClient.retrieveFileStream(new String(remote
150                     .getBytes("GBK"), "iso-8859-1"));
151             byte[] bytes = new byte[1024];
152             long step = remoteSize / 100;
153             long process = 0;
154             long localSize = 0L;
155             int c;
156             while ((c = in.read(bytes)) != -1) {
157                 out.write(bytes, 0, c);
158                 localSize += c;
159                 long nowProcess = localSize / step;
160                 if (nowProcess > process) {
161                     process = nowProcess;
162                     if (process % 10 == 0)
163                         System.out.println("下载进度:" + process);
164                     // TODO 更新文件下载进度,值存放在process变量中
165                 }
166             }
167             in.close();
168             out.close();
169             boolean upNewStatus = ftpClient.completePendingCommand();
170             if (upNewStatus) {
171                 result = DownloadStatus.Download_New_Success;
172             } else {
173                 result = DownloadStatus.Download_New_Failed;
174             }
175         }
176         return result;
177     }
178
179     /**
180      * 上传文件到FTP服务器,支持断点续传
181      *
182      * @param local
183      *            本地文件名称,绝对路径
184      * @param remote
185      *            远程文件路径,使用/home/directory1/subdirectory/file.ext或是
186      *            http://www.guihua.org /subdirectory/file.ext
187      *            按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
188      * @return 上传结果
189      * @throws IOException
190      */
191     public UploadStatus upload(String local, String remote) throws IOException {
192         // 设置PassiveMode传输
193         ftpClient.enterLocalPassiveMode();
194         // 设置以二进制流的方式传输
195         ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
196         ftpClient.setControlEncoding("GBK");
197         UploadStatus result;
198         // 对远程目录的处理
199         String remoteFileName = remote;
200         if (remote.contains("/")) {
201             remoteFileName = remote.substring(remote.lastIndexOf("/") + 1);
202             // 创建服务器远程目录结构,创建失败直接返回
203             if (CreateDirecroty(remote, ftpClient) == UploadStatus.Create_Directory_Fail) {
204                 return UploadStatus.Create_Directory_Fail;
205             }
206         }
207
208         // 检查远程是否存在文件
209         FTPFile[] files = ftpClient.listFiles(new String(remoteFileName
210                 .getBytes("GBK"), "iso-8859-1"));
211         if (files.length == 1) {
212             long remoteSize = files[0].getSize();
213             File f = new File(local);
214             long localSize = f.length();
215             if (remoteSize == localSize) {
216                 return UploadStatus.File_Exits;
217             } else if (remoteSize > localSize) {
218                 return UploadStatus.Remote_Bigger_Local;
219             }
220
221             // 尝试移动文件内读取指针,实现断点续传
222             result = uploadFile(remoteFileName, f, ftpClient, remoteSize);
223
224             // 如果断点续传没有成功,则删除服务器上文件,重新上传
225             if (result == UploadStatus.Upload_From_Break_Failed) {
226                 if (!ftpClient.deleteFile(remoteFileName)) {
227                     return UploadStatus.Delete_Remote_Faild;
228                 }
229                 result = uploadFile(remoteFileName, f, ftpClient, 0);
230             }
231         } else {
232             result = uploadFile(remoteFileName, new File(local), ftpClient, 0);
233         }
234         return result;
235     }
236
237     /**
238      * 断开与远程服务器的连接
239      *
240      * @throws IOException
241      */
242     public void disconnect() throws IOException {
243         if (ftpClient.isConnected()) {
244             ftpClient.disconnect();
245         }
246     }
247
248     /**
249      * 递归创建远程服务器目录
250      *
251      * @param remote
252      *            远程服务器文件绝对路径
253      * @param ftpClient
254      *            FTPClient 对象
255      * @return 目录创建是否成功
256      * @throws IOException
257      */
258     public UploadStatus CreateDirecroty(String remote, FTPClient ftpClient)
259             throws IOException {
260         UploadStatus status = UploadStatus.Create_Directory_Success;
261         String directory = remote.substring(0, remote.lastIndexOf("/") + 1);
262         if (!directory.equalsIgnoreCase("/")
263                 && !ftpClient.changeWorkingDirectory(new String(directory
264                         .getBytes("GBK"), "iso-8859-1"))) {
265             // 如果远程目录不存在,则递归创建远程服务器目录
266             int start = 0;
267             int end = 0;
268             if (directory.startsWith("/")) {
269                 start = 1;
270             } else {
271                 start = 0;
272             }
273             end = directory.indexOf("/", start);
274             while (true) {
275                 String subDirectory = new String(remote.substring(start, end)
276                         .getBytes("GBK"), "iso-8859-1");
277                 if (!ftpClient.changeWorkingDirectory(subDirectory)) {
278                     if (ftpClient.makeDirectory(subDirectory)) {
279                         ftpClient.changeWorkingDirectory(subDirectory);
280                     } else {
281                         System.out.println("创建目录失败");
282                         return UploadStatus.Create_Directory_Fail;
283                     }
284                 }
285                 start = end + 1;
286                 end = directory.indexOf("/", start);
287                 // 检查所有目录是否创建完毕
288                 if (end <= start) {
289                     break;
290                 }
291             }
292         }
293         return status;
294     }
295
296     /** */
297     /**
298      * 上传文件到服务器,新上传和断点续传
299      *
300      * @param remoteFile
301      *            远程文件名,在上传之前已经将服务器工作目录做了改变
302      * @param localFile
303      *            本地文件 File句柄,绝对路径
304      * @param processStep
305      *            需要显示的处理进度步进值
306      * @param ftpClient
307      *            FTPClient 引用
308      * @return
309      * @throws IOException
310      */
311     public UploadStatus uploadFile(String remoteFile, File localFile,
312             FTPClient ftpClient, long remoteSize) throws IOException {
313         UploadStatus status;
314         // 显示进度的上传
315         long step = localFile.length() / 100;
316         long process = 0;
317         long localreadbytes = 0L;
318         RandomAccessFile raf = new RandomAccessFile(localFile, "r");
319         OutputStream out = ftpClient.appendFileStream(new String(remoteFile
320                 .getBytes("GBK"), "iso-8859-1"));
321         // 断点续传
322         if (remoteSize > 0) {
323             ftpClient.setRestartOffset(remoteSize);
324             process = remoteSize / step;
325             raf.seek(remoteSize);
326             localreadbytes = remoteSize;
327         }
328         byte[] bytes = new byte[1024];
329         int c;
330         while ((c = raf.read(bytes)) != -1) {
331             out.write(bytes, 0, c);
332             localreadbytes += c;
333             if (localreadbytes / step != process) {
334                 process = localreadbytes / step;
335                 System.out.println("上传进度:" + process);
336             }
337         }
338         out.flush();
339         raf.close();
340         out.close();
341         boolean result = ftpClient.completePendingCommand();
342         if (remoteSize > 0) {
343             status = result ? UploadStatus.Upload_From_Break_Success
344                     : UploadStatus.Upload_From_Break_Failed;
345         } else {
346             status = result ? UploadStatus.Upload_New_File_Success
347                     : UploadStatus.Upload_New_File_Failed;
348         }
349         return status;
350     }
351
352     public void run() {
353         try {
354             this.connect(ftpURL, new java.lang.Integer(ftpport), username, pwd);
355             this.download(file1, file2);
356             this.disconnect();
357         } catch (IOException e) {
358             System.out.println("连接FTP出错:" + e.getMessage());
359         }
360     }
361
362 }
时间: 2024-10-29 10:48:54

FTP多线程,断点续传上传下载的相关文章

python使用ftplib模块实现FTP文件的上传下载

python已经默认安装了ftplib模块,用其中的FTP类可以实现FTP文件的上传下载 FTP文件上传下载 # coding:utf8 from ftplib import FTP def upload(f, remote_path, local_path): fp = open(local_path, "rb") buf_size = 1024 f.storbinary("STOR {}".format(remote_path), fp, buf_size) f

ftp自动登录上传下载文件

(1)ftp自动批量下载文件 #####从ftp服务器上的/data/localacc 到 本地的/data/localacc#### #!/bin/bash ftp -n<<! //-n是不使用ftp的自动登录 open 10.0.129.170 //open host[port]:建立指定ftp服务器连接,可指定连接端口 user sfhc sfhc1234 //user username password:向远程主机表明自己的身份,需要口令时,必须输入口令,如:user anonymou

Linux FTP匿名用户上传下载登录

FTP服务器192.168.62.2 第一步:vsftpd配置文件的更改 [[email protected] vsftpd]# cat vsftpd.conf # Example config file /etc/vsftpd/vsftpd.conf## The default compiled in settings are fairly paranoid. This sample file# loosens things up a bit, to make the ftp daemon m

不用FTP使用SecureCRT上传下载文件,并解决rz、sz command not found异常

使用SSH终端操作Linux/UNIX时,很多时候需要传一些文件到服务器上,或说从服务器上下载一些文件,这类文件传输动作一般使用FTP即可,但是需要架设FTP Server,每次传输不太方便,还要另外使用FTP Client,听说使用SecureCRT也能实现文件传输,就玩了一把. SecureCRT支持的文件传输协议有ASCII.X.Y.Z Modem几种,现使用X/Y/Z Modem,设置方法如下 1.在session options中设置,设置完成后记得使用save session set

iOS经验1:自己写的网络数据请求 第三方框架 断点续传 上传下载

镔哥哥做项目,一般的数据请求不管他多复杂,只要自己写好了请求,那么调用永远是那么的简单,那么我介绍一下 一:需要用到第三方框架AFNetworking,直接写在工程pch头文件里就行因为经常用到它,这在网上随便下载就行,最好用cocopod来下载,这样什么都有了,cocopod是什么,我就不说,博客上面有介绍. 开始啦: 1:自定义网络请求DataRequestManager类专门管理网络用的 朋友们以下代码就可以直接复制来用了 .h文件 //  DataRequestManager.h // 

使用.net FtpWebRequest 实现FTP常用功能 上传 下载 获取文件列表 移动 切换目录 改名 .

平时根本没时间搞FTP什么的,现在这个项目需要搞FTP,为什么呢,我给大家说下项目背景,我们的一个应用程序上需要上传图片,但是用户部署程序的服务器上不让上传任何东西,给了我们一个FTP账号和密码,让我们把图片保存到另一台所谓的文件服务器上面. 建立ftp通信,写入文件流,ok ,  但是显示的时候就麻烦了,不能直接写<img src = "ftp://121.131.131.1" />这样的代码啊,因为这样写的话,你浏览的时候还要登陆Ftp账户,每次都要弹出一个用户登陆框,

ftp实现文件上传(下载)

例子代码 package getUrlPic; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; import org.apache.commons.net.ftp.FTPClient; import org.apache.commons.net.ftp.FTPFile; import org.apache.commons.net.ftp.FTPReply; p

【FTP】FTP文件上传下载-支持断点续传

Jar包:apache的commons-net包: 支持断点续传 支持进度监控(有时出不来,搞不清原因) 相关知识点 编码格式: UTF-8等; 文件类型: 包括[BINARY_FILE_TYPE(常用)]和[ASCII_FILE_TYPE]两种; 数据连接模式:一般使用LocalPassiveMode模式,因为大部分客户端都在防火墙后面: 1. LocalPassiveMode:服务器端打开数据端口,进行数据传输: 2. LocalActiveMode:客户端打开数据端口,进行数据传输: 系统

C# FTP 上传 下载(汇总)

1.C# 上传下载ftp(支持断点续传) 2. C# FTP上传下载(支持断点续传)