applet实现大文件ftp上传(一)

由于要用APPLET实现大文件FTP上传下载,从网上搜索了几下,找到很多资料,最后决定采用基于 org.apache.commons.net.ftp包实现FTP上传下载,Net包中的类既提供对协议的底层访问也有高层的抽象。在大多数情况下,抽 象是足够的,它可以使你不必编写解析各种协议的底层套接字的代码。使用抽象不会损失任何功能。

    借此感叹,org.apache.commons开源包真是森罗万象,应有尽有。反观国内打着开源旗号的软件也不少,但没几个能在当前软林扬名立万的,借山本赵一句经典台词:悲哀 悲哀 真是悲哀。

    开发环境:winxp+eclipse3.2.2+struts2.0+jse5.0

    最早采用以下代码:

package yp;

import java.io.File;

import java.io.FileOutputStream;

import java.io.IOException;

import java.io.InputStream;

import java.io.OutputStream;

import java.io.PrintWriter;

import java.io.RandomAccessFile;

import java.util.ArrayList;

import java.util.List;

import org.apache.commons.net.PrintCommandListener;

import org.apache.commons.net.ftp.FTP;

import org.apache.commons.net.ftp.FTPClient;

import org.apache.commons.net.ftp.FTPFile;

import org.apache.commons.net.ftp.FTPReply;

 

public class ContinueFTP{   

   private File file=null;

   //是否完整保留原文件名

   private boolean isSaveFileName = true;

   //枚举上传状态

   public enum UploadStatus { 

         Create_Directory_Fail,      //远程服务器相应目录创建失败 

         Create_Directory_Success,   //远程服务器创建目录成功 

         Upload_New_File_Success,    //上传新文件成功 

         Upload_New_File_Failed,     //上传新文件失败 

         File_Exits,                 //文件已经存在 

         Remote_Bigger_Local,        //远程文件大于本地文件 

         Upload_From_Break_Success,  //断点续传成功 

         Upload_From_Break_Failed,   //断点续传失败 

         Delete_Remote_Faild;        //删除远程文件失败 

    }

   

    //枚举下载状态

    public enum DownloadStatus { 

          Remote_File_Noexist,    //远程文件不存在 

          Local_Bigger_Remote,    //本地文件大于远程文件 

          Download_From_Break_Success,    //断点下载文件成功 

          Download_From_Break_Failed,     //断点下载文件失败 

          Download_New_Success,           //全新下载文件成功 

          Download_New_Failed;            //全新下载文件失败 

    }

   

    public void init(){

    

    }

   

    public FTPClient ftpClient = new FTPClient(); 

        

     public ContinueFTP(){ 

           //设置将过程中使用到的命令输出到控制台 

           this.ftpClient.addProtocolCommandListener(new PrintCommandListener(new PrintWriter(System.out))); 

     } 

      

   

    public String getRemoteFileName(String localFileName){

     String fileName ="";

     //分隔符

     String sepaRator="\";

        if (localFileName.indexOf(sepaRator)<0)

         sepaRator="/";

        //最后分隔符位置

        int idx = localFileName.lastIndexOf(sepaRator)+1;

        fileName = localFileName.substring(idx);

        return fileName;

    }    

     

      

       public boolean isFileExist(String remoteFileName) throws IOException{

        boolean isFileExist = false;          

           //检查远程是否存在文件 

           FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1")); 

           if(files!=null && files.length >= 1){ 

              isFileExist = true;

        }

        return isFileExist;

       }

      

      

        

       public boolean connect(String hostname,int port,String username,String password) throws Exception{ 

        boolean bl = false;

        try{

         ftpClient.connect(hostname, port); 

        }catch(Exception e){

          //可具体报错到主机和端口号

      throw new BaseException("FTPConnError01",new String[]{"connect",e.getMessage()});

        }

        try{

         //ftpClient.setControlEncoding("GBK");

            if(FTPReply.isPositiveCompletion(ftpClient.getReplyCode())){ 

                if(ftpClient.login(username, password)){ 

                 bl = true; 

                } 

            }

        }catch(Exception e){

          //可具体报错到用户和密码

      throw new BaseException("FTPConnError02",new String[]{"connect",e.getMessage()});

        }

           return bl; 

       } 

        

        

       public DownloadStatus download(String remote,String local) throws Exception{ 

           //设置被动模式 

           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){ 

            throw new BaseException("CellDataInputService",new String[]{"download","远程文件"+remote+"不存在"});

           } 

            

           long lRemoteSize = files[0].getSize(); 

           File f = new File(local); 

           //本地存在文件,进行断点下载 

           if(f.exists()){ 

               long localSize = f.length(); 

               //判断本地文件大小是否大于远程文件大小 

               if(localSize >= lRemoteSize){ 

                   System.out.println("本地文件大于远程文件,下载中止"); 

                   return DownloadStatus.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; 

               int c; 

               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 = new FileOutputStream(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; 

               int c; 

               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; 

               } 

           } 

           return result; 

       }        

       public UploadStatus upload(File localFile,String remote) throws IOException{ 

           //设置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){ 

                   return UploadStatus.Create_Directory_Fail; 

               } 

           } 

            

           //检查远程是否存在文件 

           FTPFile[] files = ftpClient.listFiles(new String(remoteFileName.getBytes("GBK"),"iso-8859-1")); 

           if(files!=null && files.length == 1){ 

               long remoteSize = files[0].getSize(); 

               //File f = new File(local); 

               long localSize = localFile.length(); 

               if(remoteSize==localSize){ 

                   return UploadStatus.File_Exits; 

               }else if(remoteSize > localSize){ 

                   return UploadStatus.Remote_Bigger_Local; 

               } 

                

               //尝试移动文件内读取指针,实现断点续传 

               result = uploadFile(remoteFileName, localFile, ftpClient, remoteSize); 

                

               //如果断点续传没有成功,则删除服务器上文件,重新上传 

               if(result == UploadStatus.Upload_From_Break_Failed){ 

                   if(!ftpClient.deleteFile(remoteFileName)){ 

                       return UploadStatus.Delete_Remote_Faild; 

                   } 

                   result = uploadFile(remoteFileName, localFile, ftpClient, 0); 

               } 

           }else { 

               result = uploadFile(remoteFileName, localFile, ftpClient, 0); 

           } 

           return result; 

       } 

        

       public void disconnect() throws IOException{ 

           if(this.ftpClient.isConnected()){ 

            this.ftpClient.disconnect(); 

           } 

       } 

        

      

       public String CreateDirecroty(String remoteDir)throws IOException{

        String fillDir = "";

              UploadStatus st = CreateDirecroty(remoteDir,this.ftpClient);

              if (st == UploadStatus.Create_Directory_Success)

          fillDir = remoteDir;

        else

        fillDir = "";

             

        return fillDir;

       }

      

        

       public UploadStatus CreateDirecroty(String remote,FTPClient ftpClient) throws IOException{ 

           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("创建目录失败"); 

                           return UploadStatus.Create_Directory_Fail; 

                       } 

                   } 

                    

                   start = end + 1; 

                   end = directory.indexOf("/",start); 

                    

                   //检查所有目录是否创建完毕 

                   if(end <= start){ 

                       break; 

                   } 

               } 

           } 

           return status; 

       } 

        

        

       public UploadStatus uploadFile(String remoteFile,File localFile,FTPClient ftpClient,long remoteSize) throws IOException{ 

           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]; 

           int c; 

           while((c = raf.read(bytes))!= -1){ 

               out.write(bytes,0,c); 

               localreadbytes+=c; 

                  //TODO 汇报上传状态 

               if(localreadbytes / step != process){ 

                   process = localreadbytes / step; 

                   System.out.println("上传进度:" + process); 

               } 

           } 

           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; 

           } 

           return status; 

       } 

      

       public List<String> getRemoteFileList(String remoteDir){

         List<String> list = new ArrayList<String>();

              FTPFile[] files;

     try {

      files = ftpClient.listFiles(remoteDir);

               for (int i = 0; i < files.length; i++) {

                list.add(files[i].getName());

               }

     } catch (IOException e) {

      // TODO Auto-generated catch block

      e.printStackTrace();

     }

              return list;

        }

      

      

       public boolean deleteFile(String fillFileName) throws Exception {

        boolean bl = false;

        this.ftpClient.deleteFile(fillFileName);

           int status = this.ftpClient.getReplyCode();

           if(status == 250){

            bl = true;

            System.out.println("成功删除FTP服务器中文件:" + fillFileName);           

           }

           return bl;

       }

 

         public boolean deleteDir(String remoteDir)throws Exception {

        boolean isDel = false;

        this.ftpClient.removeDirectory(remoteDir);

           int status = this.ftpClient.getReplyCode();

           if(status == 250){

            isDel = true;

            System.out.println("成功删除FTP服务器中目录:" + remoteDir);           

           }

        return isDel;

       }

        

       public static void main(String[] args) throws Exception {

        ContinueFTP myFtp = new ContinueFTP(); 

        try { 

            long l1 = System.currentTimeMillis();

            System.out.println("begin:"+ l1);

               if (myFtp.connect("10.68.7.182", 21, "a", "a")) {

                String mkDir = myFtp.CreateDirecroty("TTT/ccc/");

                if (mkDir != null && !mkDir.trim().equals(""))

                 System.out.println("mkDir success:"+mkDir);

                //myFtp.download( "/XA01B03H05/5.mp3",file,"0");

                //myFtp.upload("/XA01B03H05/5.mp3", "/云台山.mpg");

                //myFtp.delete_file("/tmp.txt");

                //String str = new String("电视剧");

                //myFtp.ftpClient.removeDirectory("/kkk/jk/");

                //myFtp.ftpClient.makeDirectory(new String(str.getBytes("GBK"),"iso-8859-1"));

                myFtp.disconnect();

             long l2 = System.currentTimeMillis();

             System.out.println("end:"+ l2);

                System.out.println("remaining:"+(l2-l1));

               }

           } catch (IOException e) { 

               System.out.println("连接FTP出错:"+e.getMessage()); 

           }

         

       }

   public File getFile() {

    return file;

   }

   public void setFile(File file) {

    this.file = file;

   }

   public boolean isSaveFileName() {

    return isSaveFileName;

   }

   public void setSaveFileName(boolean isSaveFileName) {

    this.isSaveFileName = isSaveFileName;

   }

  

  

}

 

    通过main函数测试效果也不错,还显示上传或下载进度,再写一个对应action及jsp实现ftp上传下载,不过我吃过一次大亏,本来web服务器是本机,我原来做的上传下载都没有问题,但web服务器不在本机,就报说找不到文件!

    后来终于想明白了,系统还是web服务器上路径找文件,当然找不到。

    难道通过浏览器访问本地资源就真的无解了吗?

    当然不是,也在找了很多解决方案,各有所长,又各有短处.

1.使用表单直接提交

  这个方案肯定是被弊掉的,人一多就可能拖跨服务器.

2.使用FLASH进行文件上传

  这个方案也尝试过,不过据说AS3只支持100M左右的文件上传,大文件无法上传,不知道是不是这样?如果是这样的话,那么这个方案也将行不通了.使用FLASH进行文件上传相对而言开发不会太困难.

3.使用APPLET进行文件上传

  使用APPLET开发文件上传控件,这个对于使用JAVA来进行开发的非常方便,因为我们项目就是使用JAVA的,不过APPLET有安全策略的问题,无 法读取客户端的问题.如果要,那么用户必须修改其java.policy文件,这对于用户来讲简直是不可能的.如果使用程序下载动态修改也会比较麻烦.其 实还有一个破解之法,就是采用数字证书。

  缺点:1)、客户端必须安装JRE;2)、想办法突破APPLET有安全策略的问题

  优点:java编写,支持多浏览器

4.使用ACTIVEX进行文件上传

  这是我目前认为比较可行的方式,而且网上也有很多类似这样的控件,但是都不是免费的,所以只能自己想办法解决了.使用ACTIVEX开发,可以使用C++、DELPHI等来进行开发

  缺点:1>客户端推荐IE;2>IE安全设置中启用activex控件

  优点:ACTIVEX开发速度快、界面友好

  以下方案先采用第三种方案---Java applet,当年让Java 大火了一把的号称与微软的ActiveX 相提并论的技术当然,现在Java 出了JavaFX,是不是Applet 的替代品呢?你猜,猜不着呀?你再猜^_^

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值