2014-10-01 49 views
1

我的web應用程序提供下載。 Javascript創建點擊url(取決於用戶輸入),瀏覽器應該打開它,這樣頁面不會被重新加載。使用JavaFX下載WebView

對於這一點,我想我必須選擇:

// Alt1: 
window.open(pathToFile); 

// Alt2: 
var downloadFrame = document.getElementById('downloads'); 
if (downloadFrame === null) { 
    downloadFrame = document.createElement('iframe'); 
    downloadFrame.id = 'downloads'; 
    downloadFrame.style.display = 'none'; 
    document.body.appendChild(downloadFrame); 
} 
downloadFrame.src = pathToFile; 

下的Firefox這兩部作品。打開新窗口方法時出現的問題:如果在服務器上創建文件需要更多時間,則新的空標籤將遲到。 iframe問題:如果服務器出現錯誤,則不會給出反饋。

我認爲在Firefox上iframe是更好的解決方案。但是,Web應用程序也必須使用JavaFX WebView運行。 JavaFX沒有下載功能,我必須編寫它。一種可能的方式是聽上的位置屬性:

final WebView webView = new WebView(); 

webView.getEngine().locationProperty().addListener(new ChangeListener<String>() { 
    @Override public void changed(ObservableValue<? extends String> observableValue, String oldLoc, String newLoc) { 
     if (newLoc.cotains("/download")) { 
      FileChooser chooser = new FileChooser(); 
      chooser.setTitle("Save " + newLoc); 
      File saveFile = chooser.showSaveDialog(webView.getEngine().getScene().getWindow()); 

      if (saveFile != null) { 
       BufferedInputStream is = null; 
       BufferedOutputStream os = null; 
       try { 
        is = new BufferedInputStream(new URL(newLoc).openStream()); 
        os = new BufferedOutputStream(new FileOutputStream(saveFile)); 

        while ((readBytes = is.read()) != -1) { 
         os.write(b); 
        } 
       } finally { 
        try { if (is != null) is.close(); } catch (IOException e) {} 
        try { if (os != null) os.close(); } catch (IOException e) {} 
       } 
      } 
     } 
    } 
} 

存在一些問題:

  1. 下載開始依賴於URL的一部分,因爲JafaFX支持HTTP頭沒有訪問(這是可以忍受的)
  2. 如果用戶使用同一個url開始下載兩次,只有第一次下載工作(如果url是新的,只會觸發更改事件)。我可以創建獨特的網址(最後是#1,#2等)。但這很醜陋。
  3. 只有「window.open(pathToFile);」方法起作用。加載iframe不會觸發網站的更改位置事件。這是可以預期的,但我沒有找到合適的聽衆。

有人可以幫我解決2.或3.?

謝謝! PS:對不起,我的英語不好。

編輯: 對於2.我找到了一種方法。我不知道它是否是一個好的,如果它是高性能的,如果新的webview被刪除或下載後在緩存中,... 並且用戶沒有得到反饋,當出現問題時提高:

webView.getEngine().setCreatePopupHandler(new Callback<PopupFeatures, WebEngine>() { 
    @Override public WebEngine call(PopupFeatures config) { 
     final WebView downloader = new WebView(); 
     downloader.getEngine().locationProperty().addListener(/* The Listener from above */); 
     return downloader.getEngine(); 
    } 
} 

回答

0

我想你可能只需要使用copyURLtoFile來獲取文件...調用時的位置變化,或只是調用使用註冊的Java類。類似這樣的:

org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename)); 

使用copyURLToFile當前頁面不必提供文件。我想註冊類可能是要走的最簡單的方法......是這樣的:

PHP代碼:

<a href='#' onclick="app.getfile('$filename')">Download $filename</a> 

的Java(在線類的JavaFX類/窗...在這種情況下,我的JavaFX窗口是一個JFrame內):

public class JavaApp { 
JFrame cloudFrameREF; 
    JavaApp(JFrame cloudFrameREF) 
    { 
     this.cloudFrameREF = cloudFrameREF; 
    } 
} 
    public void getfile(String filename) { 
    String newLoc = "http://your_web_site.com/send_file.php?filename=" + filename; 
    org.apache.commons.io.FileUtils.copyURLToFile(new URL(newLoc), new File(System.getProperty("user.home")+filename)); 
    } 

這部分將走在主JavaFX類:

Platform.runLater(new Runnable() { 
     @Override 
     public void run() { 
browser2 = new WebView(); 
webEngine = browser2.getEngine(); 
appREF = new JavaApp(cloudFrame); 
webEngine.getLoadWorker().stateProperty().addListener(
     new ChangeListener<State>() { 
      @Override public void changed(ObservableValue ov, State oldState, State newState) { 

       if (newState == Worker.State.SUCCEEDED) { 
       JSObject win 
          = (JSObject) webEngine.executeScript("window"); 
// this next line registers the JavaApp class with the page... you can then call it from javascript using "app.method_name". 
        win.setMember("app", appREF); 
      } 

      } 
     }); 

你可能不需要眼鏡架參考......我被盜號一些我自己的代碼來測試這個和ref是有用的其他東西...