我需要在网页中弹出一个文件打开对话框,让用户选择一个文件(不用于上传!)。因为我需要访问完整的文件路径,所以我不能使用表单/输入。因此,我使用签名的Java小程序。
在我的测试用例中,从javascript函数调用Java applet方法。 applet方法打开一个文件打开对话框(JFileChooser)。如果闲置大约。 30英寸,小程序被Safari(*)杀死。在我的测试中,Chrome更好,它会弹出“无响应”警报,而Firefox显然不关心。
IIUC,这是一种特定于Safari的行为,但它非常不方便。我需要该对话框才能保持用户直到用户做出选择。我看了线程JFileChooser但是这条路似乎更复杂,并且由于已知的安全原因,单独使用Javascript完成所有工作是不可能的。你有一个干净的解决方案吗?
(*)JVM以InterruptedException结束
答案 0 :(得分:1)
你的问题源于这样一个事实:Java中的对话框表现为阻塞方法调用(它实际上是一个令人惊奇的工程技巧,他们希望其他工具包可以采用它)。因此,当您的javascript将方法调用到Java代码上时,它正在等待该对话框被解除。浏览器检测到javascript线程暂时没有返回,只是确定它已经死锁并将其杀死。因此,Java applet随页面一起关闭。
您需要将其转换为异步样式交互。 Javascript调用应该立即返回。您可以使用Java中的SwingUtilities.invokeLater()将该调用从Javascript调用线程中推出。然后诀窍是一旦对话框被解雇,你需要Java来调用Javascript。所以你将有javascript注册某种回调机制。像下面这样的东西。我不记得外部的javascript如何 - > java完全正常工作,所以这只是伪代码来说明这个想法:
function showFileDialog() {
applet.showFileDialog( function( filepath ) {
if( filepath ) {
alert( "Hey they picked " + filepath );
} // must have hit cancel if filepath is null
} );
}
同时在Java中:
public void showFileDialog( JavascriptFunction someJavascriptFunction ) {
SwingUtilities.invokeLater( new Runnable() {
public void run() {
JFileChooserDialog chooser = new JFileChooser();
...
int option = chooser.showOpenDialog( parent );
someJavascriptFunction.invoke( option == JFileChooser.APPROVE_OPTION ?
chooser.getSelectedFile().getAbsolutePath() :
null );
}
});
}