国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > Java > 正文

Java實現FTP批量大文件上傳下載篇2

2019-11-26 13:55:04
字體:
來源:轉載
供稿:網友

接著上一篇進行學習java文件上傳下載1。

五、斷點續傳 

對于熟用QQ的程序員,QQ的斷點續傳功能應該是印象很深刻的。因為它很實用也很方面。因此,在我們的上傳下載過程中,很實現了斷點續傳的功能。 

其實斷點續傳的原理很簡單,就在上傳的過程中,先去服務上進行查找,是否存在此文件,如果存在些文件,則比較服務器上文件的大小與本地文件的大小,如果服務器上的文件比本地的要小,則認為此文件上傳過程中應該可以進行斷點續傳。 

在實現的過程中,RandomAccessFile類變得很有用。此類的實例支持對隨機存取文件的讀取和寫入。隨機存取文件的行為類似存儲在文件系統中的一個大型字節數組。存在指向該隱含數組的光標或索引,稱為文件指針;輸入操作從文件指針開始讀取字節,并隨著對字節的讀取而前移此文件指針。如果隨機存取文件以讀取/寫入模式創建,則輸出操作也可用;輸出操作從文件指針開始寫入字節,并隨著對字節的寫入而前移此文件指針。寫入隱含數組的當前末尾之后的輸出操作導致該數組擴展。該文件指針可以通過 getFilePointer 方法讀取,并通過 seek 方法進行設置。 

RandomAccessFile類的skipBytes方法嘗試跳過輸入的 n 個字節以丟棄跳過的字節。如果從服務器上查得待上傳文件的大小n,則采用skipBytes方法可以跳過這n個字節,從而開始從新的地方開始進行斷點續傳。具體的方法說明可以參見JDK5的API說明。 

可以在net.sf.jftp.net. DataConnection類的run方法中,可以看出上傳下載中斷點續傳的實現,代碼如下: 

public void run()  {    try    {    newLine = con.getCRLF();      if(Settings.getFtpPasvMode())      {        try        {          sock = new Socket(host, port);          sock.setSoTimeout(Settings.getSocketTimeout());        }        catch(Exception ex)        {          ok = false;          debug("Can't open Socket on port " + port);        }      }      else      {        //Log.debug("trying new server socket: "+port);        try        {          ssock = new ServerSocket(port);        }        catch(Exception ex)        {          ok = false;          Log.debug("Can't open ServerSocket on port " + port);        }      }    }    catch(Exception ex)    {      debug(ex.toString());    }    isThere = true;    boolean ok = true;    RandomAccessFile fOut = null;    BufferedOutputStream bOut = null;    RandomAccessFile fIn = null;    try    {      if(!Settings.getFtpPasvMode())      {        int retry = 0;        while((retry++ < 5) && (sock == null))        {          try          {            ssock.setSoTimeout(Settings.connectionTimeout);            sock = ssock.accept();          }          catch(IOException e)          {            sock = null;            debug("Got IOException while trying to open a socket!");            if(retry == 5)            {              debug("Connection failed, tried 5 times - maybe try a higher timeout in Settings.java");            }        finished = true;            throw e;          }          finally          {            ssock.close();          }          debug("Attempt timed out, retrying");        }      }      if(ok)      {        byte[] buf = new byte[Settings.bufferSize];        start = System.currentTimeMillis();        int buflen = 0;        //---------------download,下載----------------------        if(type.equals(GET) || type.equals(GETDIR))        {          if(!justStream)          {            try            {              if(resume)              {                File f = new File(file);                fOut = new RandomAccessFile(file, "rw");                fOut.skipBytes((int) f.length());                buflen = (int) f.length();              }              else              {                if(localfile == null)                {                  localfile = file;                }                File f2 = new File(Settings.appHomeDir);                f2.mkdirs();                File f = new File(localfile);                if(f.exists())                {                  f.delete();                }                bOut = new BufferedOutputStream(new FileOutputStream(localfile),                                Settings.bufferSize);              }            }            catch(Exception ex)            {              debug("Can't create outputfile: " + file);              ok = false;              ex.printStackTrace();            }          }                //---------------upload,上傳----------------------        if(type.equals(PUT) || type.equals(PUTDIR))        {          if(in == null)          {            try            {              fIn = new RandomAccessFile(file, "r");                            if(resume)              {                fIn.skipBytes(skiplen);              }                            //fIn = new BufferedInputStream(new FileInputStream(file));            }            catch(Exception ex)            {              debug("Can't open inputfile: " + " (" + ex + ")");              ok = false;            }          }                    if(ok)          {            try            {              out = new BufferedOutputStream(sock.getOutputStream());            }            catch(Exception ex)            {              ok = false;              debug("Can't get OutputStream");            }                        if(ok)            {              try              {                int len = skiplen;                char b;                                while(true)                {                  int read;                                    if(in != null)                  {                    read = in.read(buf);                  }                  else                  {                    read = fIn.read(buf);                  }                                    len += read;                                    //System.out.println(file + " " + type+ " " + len + " " + read);                  if(read == -1)                  {                    break;                  }                                    if(newLine != null)                   {                    byte[] buf2 = modifyPut(buf, read);                    out.write(buf2, 0, buf2.length);                  }                  else                   {                    out.write(buf, 0, read);                  }                                    con.fireProgressUpdate(file, type, len);                                    if(time())                  {                    //  Log.debugSize(len, false, false, file);                  }                                    if(read == StreamTokenizer.TT_EOF)                  {                    break;                  }                }                                out.flush();                                //Log.debugSize(len, false, true, file);              }              catch(IOException ex)              {                ok = false;                debug("Error: Data connection closed.");                con.fireProgressUpdate(file, FAILED, -1);                ex.printStackTrace();              }            }          }        }      }    }    catch(IOException ex)    {      Log.debug("Can't connect socket to ServerSocket");      ex.printStackTrace();    }    finally    {      try      {        if(out != null)        {          out.flush();          out.close();        }      }      catch(Exception ex)      {        ex.printStackTrace();      }            try      {        if(bOut != null)        {          bOut.flush();          bOut.close();        }      }      catch(Exception ex)      {        ex.printStackTrace();      }            try      {        if(fOut != null)        {          fOut.close();        }      }      catch(Exception ex)      {        ex.printStackTrace();      }            try      {        if(in != null && !justStream)        {          in.close();        }                if(fIn != null)        {          fIn.close();        }      }      catch(Exception ex)      {        ex.printStackTrace();      }    }        try    {      sock.close();    }    catch(Exception ex)    {      debug(ex.toString());    }        if(!Settings.getFtpPasvMode())    {      try      {        ssock.close();      }      catch(Exception ex)      {        debug(ex.toString());      }    }        finished = true;        if(ok)    {      con.fireProgressUpdate(file, FINISHED, -1);    }    else    {      con.fireProgressUpdate(file, FAILED, -1);    }  }

六、FTP端口映射 

FTP的數據連接有PASV和PORT兩種,如果你的FTP服務器位于內網中,需要做端口映射。筆者剛開始時對FTP的網外網映射也是不怎么了解,因此開始走了不少的彎路,開始一直以為是自己的程序有問題,浪費了不少時間,希望通過這段,能讓大家在開發的時候少花或不花這些無謂的時間與精力。 

PCD上曾經有一篇文章介紹過一種直接訪問內網的方法,其實我們只要用端口映射工具,就可輕松實現穿透內網的目的?!岸丝谟成淦鳌本褪且豢钸@樣的工具,更值得一提的是,它擺脫了命令行模式,提供了圖形界面的操作環境。 

為了讓各位能更加明白,先說一下原理。假設現在有一個局域網,主機為A,局域網內除了主機外,還有一臺機器為B,B機器當然是通過主機A上網的。另外還有一臺可上網的機器為C,與A和B并不在一個局域網內。通常情況下,C機器只能訪問到A主機,而無法穿透局域網,訪問到B。而通過端口映射后,當C機器訪問主機A的指定端口時,主機A上的“端口映射器”就起作用了,它會把指定端口上的數據轉到局域網內另一臺機器的指定端口上,從而實現訪問內網機器的目的。這樣說,大家明白了吧。至于具體的如何進行配置,筆者認為應該不是件很難的事情,再說,網上這樣的圖形解釋很多,請大家參考網絡上的文章進行設置。 

當然,實現直接訪問內網的優點是顯而易見的,別的不說,起碼FTP資源是被充分利用了。不過必須提醒讀者的是,直接訪問內網可能使內網的安全性受到威脅。筆者相信大部分朋友對主機安全的重要性還是重視的,但往往會忽略內網機器的安全設置。一旦你實現了直接訪問內網,那就必須像對待主機一樣對待內網機器,否則你的整個網絡將可能處于危險狀態。 

訪問客戶端資源

Java應用程序環境的安全策略,對于不同的代碼所擁有的不同資源的許可,它由一個Policy對象來表達。為了讓Applet(或者運行在 SecurityManager下的一個應用程序)能夠執行受保護的行為,例如讀寫文件,Applet(或 Java應用程序)必須獲得那項操作的許可,安全策略文件就是用來實現這些許可。 

Policy對象可能有多個實體,雖然任何時候只能有一個起作用。當前安裝的Policy對象,在程序中可以通過調用getPolicy方法得到,也可以通過調用setPolicy方法改變。Policy對象評估整個策略,返回一個適當的Permissions對象,詳細說明哪些代碼可以訪問哪些資源。策略文件可以儲存在無格式的ASCII文件或Policy類的二進制文件或數據庫中。本文僅討論無格式的ASCII文件的形式。 

在實際使用中,我們可以不需要自己手動去編寫那么復雜的java.policy文件,特別是在不使用數字簽名時。這時,我們完全可以借鑒JRE提供給我們的現成的 C:/Program Files/Java/jre1.5.0_12/lib/security/java.policy文件,根據我們的需要做相應的修改,本文就針對不使用數字簽名情況編寫安全策略文件。下面,是一個完整的在Windows NT/XP下使用的java.policy文件。在文件中,分別使用注釋的形式說明了每個“permission”記錄的用途。當然,不同的程序對資源訪問權限的要求可能不一樣,可以根據項目需要進行調整與選擇。 

grant  {     //對系統和用戶目錄“讀”的權限    permission  java.util.PropertyPermission  "user.dir",  "read";      permission  java.util.PropertyPermission  "user.home",  "read";      permission  java.util.PropertyPermission  "java.home",  "read";      permission  java.util.PropertyPermission  "java.class.pat",  "read";      permission  java.util.PropertyPermission  "user.name",  "read";      //對線程和線程組的操作權限    permission  java.lang.RuntimePermission  "accessClassInPackage.sun.misc";      permission  java.lang.RuntimePermission  "accessClassInPackage.sun.audio";      permission  java.lang.RuntimePermission  "modifyThread";      permission  java.lang.RuntimePermission  "modifyThreadGroup";      permission  java.lang.RuntimePermission  "loadLibrary.*";      //讀寫文件的權限    permission  java.io.FilePermission  "<<ALL  FILES>>",  "read";      permission  java.io.FilePermission  "${user.dir}${/}jmf.log",  "write";      permission  java.io.FilePermission  "${user.home}${/}.JMStudioCfg",  "write";      permission  java.net.SocketPermissio  "*",  "connect,accept";      permission  java.io.FilePermission  "C:/WINNT/TEMP/*",  "write";      permission  java.io.FilePermission  "C:/WINNT/TEMP/*",  "delete";      permission  java.awt.AWTPermission  "showWindowWithoutWarningBanner";      permission  javax.sound.sampled.AudioPermission  "record";   // //操作Socket端口的各種權限    permission  java.net.SocketPermission  "-",  "listen";      permission  java.net.SocketPermission  "-",  "accept";      permission  java.net.SocketPermission  "-",  "connect";      permission  java.net.SocketPermission  "-",  "resolve";      permission  java.security.AllPermission;     };  grant  signedBy  "saili"  {     permission  java.net.SocketPermission  "*:1024-65535",  "connect,accept,resolve";      permission  java.net.SocketPermission  "*:80",  "connect";      permission  java.net.SocketPermission  "-",  "listen,  accept,  connect,  listen,  resolve",  signedBy  "ganja";      permission  java.net.SocketPermission  "-",  "accept";      permission  java.net.SocketPermission  "-",  "connect";      permission  java.net.SocketPermission  "-",  "resolve";      permission  java.security.AllPermission;     };

筆者在本項目中,為了使用客戶端的用戶設置更加的方便與簡單,將上面的文件采用VB或C#來做成一個小程序來寫。然后將JRE及些exe共同打成一個EXE包,當JRE安裝完成后,此小程序負責找到JRE在操作系統中的安裝路徑,并在程序中寫出此java.policy文件,覆蓋原有的文件。如此一來,用戶就只需安裝一個EXE文件,從而簡化了安裝的操作次數。 

七、Applet回調服務器

JavaScript與Applet之間能夠相互通訊給我們帶來了很多方便,Java與JavaScript互相補充,以開發功能更完美的Web應用程序。B/S下能夠充分利用java的優勢,給我們帶來更多的網絡體驗,方便用戶。筆者用的比較多的是利用Swing組件開發的應用程序利用Applet實現B/s下架構,這樣能夠充分顯示Swing組件的優勢,便于系統升級,便于維護;還有就是在WEB下,有時客戶端要使用本地的硬件資源,筆者所知道的是通過Applet來實現,通過Applet去調用javaAPI來實現。 我們具體來看看JavaScript與Applet之間到底是怎樣通訊的呢? 

1.JavaScript訪問Applet

<applet name="appletName" ....../>//JavaScript訪問Applet屬性。

window.document.appletName.appletField (屬性必須是public的,"window.document."也可以不寫) //JavaScript訪問Applet方法。

window.document.appletName.appletMethod (方法必須是public的,"window.document."也可以不寫)。 

2.Applet訪問JavaScript 

Live Connect提供了Java與JavaScript的接口,可以允許在Java Applet小程序中使用JavaScript。 

需要用到一個jar包,在C:/Program Files/Java/目錄下找,大概有5M多,其實就是打開看哪個有netscape.javascript.JSObject。如果沒有裝個NetScape或從網上下都可以。 可以把它重命名為netscape.jar(不是必須的),一定要加入到classpath,目的是使開發的時候能夠編譯。特別注意的是:部署時不需要包括netscape.jar,因為整個包會下載到客戶端,影響速度。

 //引入netscape類import netscape.javascript.JSObject; import netscape.javascript.JSException; //可允許在小程序中處理異常事件public void callJavaScript(String callBackJavascript) {  JSObject window = JSObject.getWindow(this); // 獲取JavaScript窗口句柄,引用當前文檔窗口  JSObject docment = (JSObject) window.getMember("document");    form=(JSObject)doc.getMember("textForm"); //訪問JavaScript form對象     textField=(JSObject)form.getMember("textField");訪問JavaScript text對象      text=(String) textField.getMember("value"); //獲取文本區的值  // 調用JavaScript的alert()方法  // window.eval("alert(/"This alert comes from Java!/")");  window.call(callBackJavascript, null);// 參數用數組的形式表示。  }

八、運行效果 

1.上傳

(1).啟動上傳上面


(2).上傳中


(3).上傳中


(4).上傳成功


2.下載

(1)下載文件的保存路徑


(2)下載中


(3)下載中


(4)下載成功


九、小結

在本文中,筆者將在實際項目中的上傳下載問題的解決方案進行了闡述,通過采用FTP協議,來達到批量的,基本Web的大文件的上傳下載。同時通過Applet技術實現在客戶端對本地資源進行訪問。就一些大家經常遇到的實際功能如進度條、斷點續傳、FTP內外網映射等問題進行了初步的探討。這是筆者基于一些FTP的Java客戶端庫的基礎應用。希望對讀者有一定的借鑒作用。對其中一些未盡事宜進行補充。還有一些比較容易而且網上都有說明或實例的內容在此沒有一一列舉。如FTP在服務器端Serv-U軟件如何建立FTP服務、Applet在JSP頁面中的嵌入方式及參數傳遞方法、在Eclipse或是NetBeans下開始Applet等內容,由于篇幅的限制,并沒有詳盡描述,請讀者參考網上的例子或其他參考資料。

下載地址http://xiazai.VeVB.COm/201608/yuanma/FTPTransfer(VeVB.COm).rar

注釋,考慮到版權的問題,沒有把JAVA類文件發上來,不過這樣的JAR文件如何還原成java文件,我想大家已經是很熟悉了吧,呵呵.

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持武林網。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 水城县| 福清市| 图木舒克市| 衡南县| 北宁市| 浦东新区| 江口县| 如东县| 特克斯县| 雷山县| 大名县| 炎陵县| 会同县| 建平县| 英超| 长丰县| 孝感市| 同德县| 香格里拉县| 镇江市| 景泰县| 基隆市| 岑溪市| 崇文区| 东明县| 凯里市| 仲巴县| 高碑店市| 辉县市| 黄陵县| 日喀则市| 长武县| 南部县| 钦州市| 化德县| 西青区| 青浦区| 盱眙县| 三台县| 阿勒泰市| 伊宁县|