Code highlighting produced by Actipro CodeHighlighter (freeware)http://www.CodeHighlighter.com/-->import java.io.File;
importjava.io.FileOutputStream;importjava.io.IOException;importjava.io.InputStream;importjava.io.OutputStream;importjava.io.PrintWriter;importjava.io.RandomAccessFile;importopen.mis.data.DownloadStatus;importopen.mis.data.UploadStatus;importorg.apache.commons.net.PrintCommandListener;importorg.apache.commons.net.ftp.FTP;importorg.apache.commons.net.ftp.FTPClient;importorg.apache.commons.net.ftp.FTPFile;importorg.apache.commons.net.ftp.FTPReply;/** *//*** 支持断点续传的FTP实用类
*@authorBenZhouhttp://www.bt285.cn*@version0.1 实现基本断点上传下载
*@version0.2 实现上传下载进度汇报
*@version0.3 实现中文目录创建及中文文件创建,添加对于中文的支持*/
public classContinueFTP {public FTPClient ftpClient = newFTPClient();publicContinueFTP(){//设置将过程中使用到的命令输出到控制台
this.ftpClient.addProtocolCommandListener(new PrintCommandListener(newPrintWriter(System.out)));
}/** *//*** 连接到FTP服务器
*@paramhostname 主机名
*@paramport 端口
*@paramusername 用户名
*@parampassword 密码
*@return是否连接成功
*@throwsIOException*/
public boolean connect(String hostname,int port,String username,String password) throwsIOException{
ftpClient.connect(hostname, port);
ftpClient.setControlEncoding("GBK");if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){if(ftpClient.login(username, password)){return true;
}
}
disconnect();return false;
}/** *//*** 从FTP服务器上下载文件,支持断点续传,上传百分比汇报
*@paramremote 远程文件路径
*@paramlocal 本地文件路径
*@return上传的状态
*@throwsIOException*/
public DownloadStatus download(String remote,String local) throwsIOException{//设置被动模式
ftpClient.enterLocalPassiveMode();//设置以二进制方式传输
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
DownloadStatus result;//检查远程文件是否存在
FTPFile[] files = ftpClient.listFiles(new String(remote.getBytes("GBK"),"iso-8859-1"));if(files.length != 1){
System.out.println("远程文件不存在");returnDownloadStatus.Remote_File_Noexist;
}long lRemoteSize = files[0].getSize();
File f= newFile(local);//本地存在文件,进行断点下载
if(f.exists()){long localSize =f.length();//判断本地文件大小是否大于远程文件大小
if(localSize >=lRemoteSize){
System.out.println("本地文件大于远程文件,下载中止");returnDownloadStatus.Local_Bigger_Remote;
}//进行断点续传,并记录状态
FileOutputStream out = new FileOutputStream(f,true);
ftpClient.setRestartOffset(localSize);
InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));byte[] bytes = new byte[1024];long step = lRemoteSize /100;long process=localSize /step;intc;while((c = in.read(bytes))!= -1){
out.write(bytes,0,c);
localSize+=c;long nowProcess = localSize /step;if(nowProcess >process){
process=nowProcess;if(process % 10 == 0)
System.out.println("下载进度:"+process);//TODO 更新文件下载进度,值存放在process变量中
}
}
in.close();
out.close();boolean isDo =ftpClient.completePendingCommand();if(isDo){
result=DownloadStatus.Download_From_Break_Success;
}else{
result=DownloadStatus.Download_From_Break_Failed;
}
}else{
OutputStream out= newFileOutputStream(f);
InputStream in= ftpClient.retrieveFileStream(new String(remote.getBytes("GBK"),"iso-8859-1"));byte[] bytes = new byte[1024];long step = lRemoteSize /100;long process=0;long localSize = 0L;intc;while((c = in.read(bytes))!= -1){
out.write(bytes,0, c);
localSize+=c;long nowProcess = localSize /step;if(nowProcess >process){
process=nowProcess;if(process % 10 == 0)
System.out.println("下载进度:"+process);//TODO 更新文件下载进度,值存放在process变量中
}
}
in.close();
out.close();boolean upNewStatus =ftpClient.completePendingCommand();if(upNewStatus){
result=DownloadStatus.Download_New_Success;
}else{
result=DownloadStatus.Download_New_Failed;
}
}returnresult;
}/** *//*** 上传文件到FTP服务器,支持断点续传
*@paramlocal 本地文件名称,绝对路径
*@paramremote 远程文件路径,使用/home/directory1/subdirectory/file.ext或是http://www.guihua.org/subdirectory/file.ext 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
*@return上传结果
*@throwsIOException*/
public UploadStatus upload(String local,String remote) throwsIOException{//设置PassiveMode传输
ftpClient.enterLocalPassiveMode();//设置以二进制流的方式传输
ftpClient.setFileType(FTP.BINARY_FILE_TYPE);
ftpClient.setControlEncoding("GBK");
UploadStatus result;//对远程目录的处理
String remoteFileName =remote;if(remote.contains("/")){
remoteFileName= remote.substring(remote.lastIndexOf("/")+1);//创建服务器远程目录结构,创建失败直接返回
if(CreateDirecroty(remote, ftpClient)==UploadStatus.Create_Directory_Fail){returnUploadStatus.Create_Directory_Fail;
}
}//检查远程是否存在文件
FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1"));if(files.length == 1){long remoteSize = files[0].getSize();
File f= newFile(local);long localSize =f.length();if(remoteSize==localSize){returnUploadStatus.File_Exits;
}else if(remoteSize >localSize){returnUploadStatus.Remote_Bigger_Local;
}//尝试移动文件内读取指针,实现断点续传
result =uploadFile(remoteFileName, f, ftpClient, remoteSize);//如果断点续传没有成功,则删除服务器上文件,重新上传
if(result ==UploadStatus.Upload_From_Break_Failed){if(!ftpClient.deleteFile(remoteFileName)){returnUploadStatus.Delete_Remote_Faild;
}
result= uploadFile(remoteFileName, f, ftpClient, 0);
}
}else{
result= uploadFile(remoteFileName, new File(local), ftpClient, 0);
}returnresult;
}/** *//*** 断开与远程服务器的连接
*@throwsIOException*/
public void disconnect() throwsIOException{if(ftpClient.isConnected()){
ftpClient.disconnect();
}
}/** *//*** 递归创建远程服务器目录
*@paramremote 远程服务器文件绝对路径
*@paramftpClient FTPClient对象
*@return目录创建是否成功
*@throwsIOException*/
public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throwsIOException{
UploadStatus status=UploadStatus.Create_Directory_Success;
String directory= remote.substring(0,remote.lastIndexOf("/")+1);if(!directory.equalsIgnoreCase("/")&&!ftpClient.changeWorkingDirectory(new String(directory.getBytes("GBK"),"iso-8859-1"))){//如果远程目录不存在,则递归创建远程服务器目录
int start=0;int end = 0;if(directory.startsWith("/")){
start= 1;
}else{
start= 0;
}
end= directory.indexOf("/",start);while(true){
String subDirectory= new String(remote.substring(start,end).getBytes("GBK"),"iso-8859-1");if(!ftpClient.changeWorkingDirectory(subDirectory)){if(ftpClient.makeDirectory(subDirectory)){
ftpClient.changeWorkingDirectory(subDirectory);
}else{
System.out.println("创建目录失败");returnUploadStatus.Create_Directory_Fail;
}
}
start= end + 1;
end= directory.indexOf("/",start);//检查所有目录是否创建完毕
if(end <=start){break;
}
}
}returnstatus;
}/** *//*** 上传文件到服务器,新上传和断点续传
*@paramremoteFile 远程文件名,在上传之前已经将服务器工作目录做了改变
*@paramlocalFile 本地文件File句柄,绝对路径
*@paramprocessStep 需要显示的处理进度步进值
*@paramftpClient FTPClient引用
*@return*@throwsIOException*/
public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throwsIOException{
UploadStatus status;//显示进度的上传
long step = localFile.length() / 100;long process = 0;long localreadbytes = 0L;
RandomAccessFile raf= new RandomAccessFile(localFile,"r");
OutputStream out= ftpClient.appendFileStream(new String(remoteFile.getBytes("GBK"),"iso-8859-1"));//断点续传
if(remoteSize>0){
ftpClient.setRestartOffset(remoteSize);
process= remoteSize /step;
raf.seek(remoteSize);
localreadbytes=remoteSize;
}byte[] bytes = new byte[1024];intc;while((c = raf.read(bytes))!= -1){
out.write(bytes,0,c);
localreadbytes+=c;if(localreadbytes / step !=process){
process= localreadbytes /step;
System.out.println("上传进度:" +process);//TODO 汇报上传状态
}
}
out.flush();
raf.close();
out.close();boolean result =ftpClient.completePendingCommand();if(remoteSize > 0){
status= result?UploadStatus.Upload_From_Break_Success:UploadStatus.Upload_From_Break_Failed;
}else{
status= result?UploadStatus.Upload_New_File_Success:UploadStatus.Upload_New_File_Failed;
}returnstatus;
}public static voidmain(String[] args) {
ContinueFTP myFtp= newContinueFTP();try{
myFtp.connect("192.168.21.181", 21, "nid", "123");//myFtp.ftpClient.makeDirectory(new String("电视剧".getBytes("GBK"),"iso-8859-1"));//myFtp.ftpClient.changeWorkingDirectory(new String("电视剧".getBytes("GBK"),"iso-8859-1"));//myFtp.ftpClient.makeDirectory(new String("走西口".getBytes("GBK"),"iso-8859-1"));//System.out.println(myFtp.upload("http://www.5a520.cn/yw.flv", "/yw.flv",5));//System.out.println(myFtp.upload("http://www.5a520.cn/走西口24.mp4","/央视走西口/新浪网/走西口24.mp4"));
System.out.println(myFtp.download("/央视走西口/新浪网/走西口24.mp4", "E:\\走西口242.mp4"));
myFtp.disconnect();
}catch(IOException e) {
System.out.println("连接FTP出错:"+e.getMessage());
}
}
}