2014-10-01 293 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是有用的其他东西...