APPLET实现大文件FTP上传

      由于要实现大文件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;

/**
 * FTP上传下载文件
 * 支持断点续传
 * @version: 2009-10-23 下午04:28:48
 */
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))); 
     } 
      
    /**
     * 功能:通过本地文件名指定远程文件名
     * @param localFileName
     * @return
     * String
     * 范例:
     */
    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;
    }    
     
       /**
        * 功能:检查远程是否存在文件 
        * @param remoteFileName 远程文件名
        * @return
        * @throws IOException
        * boolean
        * 范例:
        */
       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;
       }
      
      
       /**
        * 连接到FTP服务器
       
        * @param hostname 主机名
        * @param port 端口
        * @param username 用户名
        * @param password 密码
        * @return 是否连接成功
        * @throws IOException
        */ 
       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; 
       } 
        
       /**
        * 从FTP服务器上下载文件,支持断点续传,上传百分比汇报
        * @param remote 远程文件路径
        * @param local 本地文件路径
        * @return 上传的状态
        * @throws IOException
        */ 
       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; 
       } 

       /**
        * 上传文件到FTP服务器,支持断点续传
        * @param local 本地文件名称,绝对路径
        * @param remote 远程文件路径,使用/home/directory1/subdirectory/file.ext 按照Linux上的路径指定方式,支持多级目录嵌套,支持递归创建不存在的目录结构
        * @return 上传结果
        * @throws IOException
        */ 
       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; 
       } 
       /**
        * 断开与远程服务器的连接
       
        * @throws IOException
        */ 
       public void disconnect() throws IOException{ 
           if(this.ftpClient.isConnected()){ 
            this.ftpClient.disconnect(); 
           } 
       } 
        
       /**
        * 功能:创建目录
        *      若传入路径已经存在,则返回该路径,否则创建
        *      目前暂不支持中文列名
        * @param remoteDir
        * @return
        * @throws IOException
        * String
        * 范例:
        */
       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;
       }
      
       /**
        * 递归创建远程服务器目录
        * @param remote 远程服务器文件绝对路径
        * @param ftpClient FTPClient对象
        * @return 目录创建是否成功
        * @throws IOException
        */ 
       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; 
       } 
        
       /**
        * 上传文件到服务器,新上传和断点续传
        * @param remoteFile 远程文件名,在上传之前已经将服务器工作目录做了改变
        * @param localFile 本地文件File句柄,绝对路径
        * @param processStep 需要显示的处理进度步进值
        * @param ftpClient FTPClient引用
        * @return
        * @throws IOException
        */ 
       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; 
       } 
       /**
        * 功能:获得远程文件列表
        * @param remoteDir 远程路径
        * @return
        * List<String>
        * 范例:
        */
       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;
        }
      
       /**
        * 功能:删除指定远程文件
        * @param fillFileName 包括路径的完整文件名
        * @return
        * @throws Exception
        * boolean
        * 范例:
        */
       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;
       }
      
       /**
        * 功能:删除指定远程路径        
        * @param remoteDir
        * @return
        * @throws Exception
        * boolean
        * 范例:
        */
       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 的替代品呢?你猜,猜不着呀?你再猜^_^

 

package yp;

import java.applet.Applet;
import java.io.File;

import javax.swing.JButton;
import javax.swing.JFileChooser;
import javax.swing.filechooser.FileFilter;

 

 /**
  * 说明:本APPLET只是测试大文件FTP上传可行性

  * 至于其他功能比如FTP下载、删除、FTP服务器文件列表可调用ContinueFTP相应功能。
  */

public class FileFtpApplet extends Applet  {

 /**
  * Constructor of the applet.
  *
  * @exception HeadlessException if GraphicsEnvironment.isHeadless()
  * returns true.
  */
/* public FileFtpApplet() throws HeadlessException {
  super();
 }*/

 /**
  * Called by the browser or applet viewer to inform
  * this applet that it is being reclaimed and that it should destroy
  * any resources that it has allocated. The <code>stop</code> method
  * will always be called before <code>destroy</code>. <p>
  *
  * A subclass of <code>Applet</code> should override this method if
  * it has any operation that it wants to perform before it is
  * destroyed. For example, an applet with threads would use the
  * <code>init</code> method to create the threads and the
  * <code>destroy</code> method to kill them. <p>
  */
 public void destroy() {
  // Put your code here
 }

 /**
  * Returns information about this applet. An applet should override
  * this method to return a <code>String</code> containing information
  * about the author, version, and copyright of the applet. <p>
  *
  * @return  a string containing information about the author, version, and
  * copyright of the applet.
  */
 public String getAppletInfo() {
  return "This is my default applet created by Eclipse";
 }

 /**
  * Called by the browser or applet viewer to inform
  * this applet that it has been loaded into the system. It is always
  * called before the first time that the <code>start</code> method is
  * called. <p>
  *
  * A subclass of <code>Applet</code> should override this method if
  * it has initialization to perform. For example, an applet with
  * threads would use the <code>init</code> method to create the
  * threads and the <code>destroy</code> method to kill them. <p>
  */
 public void init() {
  // Put your code here
 }

 /**
  * Called by the browser or applet viewer to inform
  * this applet that it should start its execution. It is called after
  * the <code>init</code> method and each time the applet is revisited
  * in a Web page. <p>
  *
  * A subclass of <code>Applet</code> should override this method if
  * it has any operation that it wants to perform each time the Web
  * page containing it is visited. For example, an applet with
  * animation might want to use the <code>start</code> method to
  * resume animation, and the <code>stop</code> method to suspend the
  * animation. <p>
  */
 public void start() {
  // Put your code here
 }

 /**
  * Called by the browser or applet viewer to inform
  * this applet that it should stop its execution. It is called when
  * the Web page that contains this applet has been replaced by
  * another page, and also just before the applet is to be destroyed. <p>
  *
  * A subclass of <code>Applet</code> should override this method if
  * it has any operation that it wants to perform each time the Web
  * page containing it is no longer visible. For example, an applet
  * with animation might want to use the <code>start</code> method to
  * resume animation, and the <code>stop</code> method to suspend the
  * animation. <p>
  */
 public void stop() {
  // Put your code here
 }
    private static final long serialVersionUID = 1L;

    private FileFtpApplet jFrame = null;

    private JButton jFileButton = null;

    public FileFtpApplet() {
   // TODO Auto-generated constructor stub
   jFrame = this;
   this.setSize(496, 260);
   jFileButton = new JButton("打开文件");
   jFrame.add(jFileButton);
   jFileButton.addMouseListener(new java.awt.event.MouseAdapter() {
       public void mouseClicked(java.awt.event.MouseEvent e) {
     // System.out.println("mouseClicked()"); // TODO
     // Auto-generated Event stub mouseClicked()
     JFileChooser jfChooser = new JFileChooser("D://..//..");
     jfChooser.setDialogTitle("打开并上传文件");
     jfChooser.setFileFilter(new FileFilter() {
         @Override
         public boolean accept(File f) {
       if (f.getName().endsWith("dat") || f.isDirectory())
           return true;
       return false;
         }
         @Override
         public String getDescription() {
       // TODO Auto-generated method stub
       return "数据文件(*.dat)";
         }
     });
     int result = jfChooser.showOpenDialog(jFrame);
     if (result == JFileChooser.APPROVE_OPTION) { // 确认打开
 
         File fileIn = jfChooser.getSelectedFile();
 
         if (fileIn.exists()) {
           //JOptionPane.showMessageDialog(jFrame, "OPEN"); // 提示框
         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  remotePath = "/";
           String remoteFile = myFtp.getRemoteFileName(fileIn.getName());
           if (remotePath == null || remotePath.trim().equals(""))
            remotePath = "/";
           //文件扩展名
           String kzNm = "";
           if (remoteFile.indexOf(".")>=0)
            kzNm = remoteFile.substring(remoteFile.indexOf("."));
           String cellCode = "yp";
           boolean isSaveFileName  = false;
           //若不保留原文件,则重新组装远程文件名
           if (!isSaveFileName)
           remoteFile= cellCode+"_"+System.currentTimeMillis()+kzNm;
           //获得远程路径最后一位
           String lastStr = remotePath.substring(remotePath.length()-1);
           if (lastStr.trim().equals("/"))
            remoteFile = remotePath + cellCode + "/" + remoteFile;
           else 
            remoteFile = remotePath + "/" +cellCode + "/" + remoteFile;
                
                 myFtp.upload(fileIn, remoteFile);
                 myFtp.disconnect();
              long l2 = System.currentTimeMillis();
              System.out.println("end:"+ l2);
                 System.out.println("remaining:"+(l2-l1));
                }
            } catch (Exception e1) { 
                System.out.println("连接FTP出错:"+e1.getMessage()); 
            }
       } else {
         }
     } else if (result == JFileChooser.CANCEL_OPTION) {
         System.out.println("Cancel button is pushed.");
     } else if (result == JFileChooser.ERROR_OPTION) {
         System.err.println("Error when select file.");
     }

      }
   }
  );
  }
}

 

    接下来问题:如何把上述JAVA类编译结果打包成jar文件,方法有很多,比如eclipse导出,java自带命令、winrar工具等。

    笔者在打包jar遇到一个问题,只打包上述java类编译结果,报错找不到yp.FileFtpApplet.class,经请教别人采取把所用的commons-net-2.0.jar、commons-net-ftp-2.0.jar解压后与java类编译结果一起打包成一个jar,搞定。

    下一步呢,当然就是对这个jar文件进行数字证书包装。流程如下:

<1>、生成密匙证书(key certificate),该证书将存储在你的.keystore文件中。Validity指的是密匙的有效期,默认是180,但是这里我们需要一年的时间,所以我们设置为365
keytool -genkey -alias FileFtpApplet -validity 365 -keystore FileFtpApplet.keystore
<2>、用我们的密匙来设计我们的APPLET
jarsigner -keystore FileFtpApplet.keystore FileFtpApplet.jar FileFtpApplet
<3>、导出证书
keytool -export -keystore FileFtpApplet.keystore -alias FileFtpApplet -file FileFtpApplet.cer

    写一个html文件对这个applet调用:

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>My applet 'FileFtpApplet' starting page</title>  
    <meta http-equiv="keywords" content="keyword1,keyword2,keyword3">
    <meta http-equiv="description" content="this is my page">
    <meta http-equiv="content-type" content="text/html; charset=UTF-8">     
  </head>
  <body>  
    <applet codebase="."
            code="yp.FileFtpApplet.class"
            name="FileFtpApplet"
            width="320"
            height="240">  
    </applet>
  </body>
</html>

    拷贝你签名的JAR文件到放置你先前的TestApplet.htmlFileFtpApplet.jar的那个目录中,然后覆盖FileFtpApplet.jar文件。在浏览器中浏览TestApplet.html。然后你的Applet会加载,并显示一个窗口,询问你是否接受或者拒绝这个签名的APPLET。点击“No”将以旧的未签名的版本来显示APPLET,那样它仍然位于沙盒中且对外面的世界有很多约束。点击“Yes”将以你的APPLET获得更多的自由。这里,我们点击“Yes”,我们的APPLET被打开。

 

 

参考资料

http://zhouzaibao.javaeye.com/blog/342766
http://hi.baidu.com/cslinmj/blog/item/ee009ae9f27b9c3cb80e2deb.html

http://203.208.37.132/search?q=cache:SfB7ntuoAWQJ:www.javaeye.com/topic/152374+applet+%E6%95%B0%E6%8D%AE%E8%AF%81%E4%B9%A6+ftp&cd=4&hl=zh-CN&ct=clnk&gl=cn&st_usg=ALhdy2-pgXZBH8X4GhIiABPkQLvKojiyIg

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值