Search code examples
javahtmljavafxwebkit

how to add a local img with file://... in javafx webkit


I want to show a picture in javafx webview local html. here is my code, But I found the picture can not be shown.The image url is "file:/D:/a.jpg".

enter image description here

//Main WebViewBrowser.java

public class WebViewBrowser extends Application {

    @Override public void start(Stage stage) throws Exception {
        WebView browser = new WebView();
        browser.setContextMenuEnabled(false);
        WebEngine webEngine = browser.getEngine();
        String url = this.getClass().getResource("t.html").toExternalForm();
        System.out.println(url);
        //out put is "jar:file:/D:/data/netbeans/WebViewBrowser1/dist/run690102893/WebViewBrowser.jar!/webviewbrowser/t.html"
        Scene scene = new Scene(browser);
        webEngine.load(url);
        stage.setScene(scene);
        stage.show();
    }

    public static void main(String[] args) {
        launch(args);
    }
}


//t.html
//.............
<html>
<head>
    <title>TODO supply a title</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body>
    <div>TODO write content</div>
    <img src="a.jpg" alt="aaa"/>  <!-- the relative path works -->
    <img src="file:/D:/a.jpg" alt="aaa"/>  <!-- the absolute path dos not work.why ?-->
</body>
 </html>

I just want to know how i can load the image which url is like 'file:/D:/a.jpg'. Thak you very much.


Solution

  • With the new description of your problem, I can reproduce it too: it seems WebView can't access to local files if the web page is loaded from a jar file.

    After searching for a while, I've just found this bug report on JIRA (you need to be registered to access to it):

    • RT-39031 [WebView] local images not loaded when web page is loaded from jar file

    As it is pointed out in the report, if you right-click over the alt description, you can load the image on a new window, what means it's not a problem of security restrictions (sandbox).

    For the moment there's no easy solution. One that is proposed also here is encoding the image as a base64 string:

    <img src="data:image/png;base64,(...)" />
    
    public String pathToBase64(String path) throws IOException {
        return Base64.getEncoder().encodeToString(Files.readAllBytes(Paths.get(path)));
    } 
    

    Other solution is using webEngine.loadContent(). There's already an example here that may work.

    EDIT

    As the OP points out, there's another workaround to deal with local images loading, based on the use of a custom URL protocol. In this question there's already a working solution. For the image loading this is a possible implementation:

    private void loadImage() throws IOException {
        String imgPath = getURL().toExternalForm();
        String ext = imgPath.substring(imgPath.lastIndexOf('.')+1);
        imgPath = imgPath.startsWith(PROTOCOL+"://") ? 
                     imgPath.substring((PROTOCOL+"://").length()) :
                     imgPath.substring((PROTOCOL+":").length());
    
        try{
            BufferedImage read = ImageIO.read(new File(imgPath));
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            ImageIO.write(read, ext, os);
            data=os.toByteArray();
        } catch(IOException ioe){
            System.out.println("IO exception: "+ioe);
        }
    }