禁用Webview中的自动图像加载/

时间:2012-09-21 05:09:39

标签: webview webkit javafx

我正在使用JavaFX webview开发Web scraper。为了疤痕的目的,我不需要加载图像。当加载页面时,Webkit会产生大量的UrlLoader线程。所以我认为最好禁用图像,这样我就可以节省大量的系统资源。有谁知道如何在Webview中禁用自动图像加载?

2 个答案:

答案 0 :(得分:4)

解决方案方法

为http定义自己的协议处理程序,并使用图像mime类型或内容过滤掉任何内容。

URL.setURLStreamHandlerFactory(new HandlerFactory());

示例代码

import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.layout.StackPane;
import javafx.scene.web.*;
import javafx.stage.Stage;

import java.io.IOException;
import java.net.*;

public class LynxView extends Application {
    private static final String BLANK_IMAGE_LOC =
            "https://upload.wikimedia.org/wikipedia/commons/c/ce/Transparent.gif";
    public static final String WEBSITE_LOC =
            "http://fxexperience.com";
    public static final String IMAGE_MIME_TYPE_PREFIX =
            "image/";

    @Override
    public void start(Stage stage) throws Exception {
        WebView webView = new WebView();
        WebEngine engine = webView.getEngine();
        engine.load(WEBSITE_LOC);

        stage.setScene(new Scene(new StackPane(webView)));
        stage.show();
    }

    public static void main(String[] args) throws IOException {
        URL.setURLStreamHandlerFactory(new URLStreamHandlerFactory() {
            @Override
            public URLStreamHandler createURLStreamHandler(String protocol) {
                if ("http".equals(protocol)) {
                    return new sun.net.www.protocol.http.Handler() {
                        @Override
                        protected URLConnection openConnection(URL url, Proxy proxy) throws IOException {
                            String[] fileParts = url.getFile().split("\\?");
                            String contentType = URLConnection.guessContentTypeFromName(fileParts[0]);
                            // this small hack is required because, weirdly, svg is not picked up by guessContentTypeFromName
                            // because, for Java 8, svg is not in $JAVA_HOME/lib/content-types.properties
                            if (fileParts[0].endsWith(".svg")) {
                                 contentType = "image/svg";
                            }
                            System.out.println(url.getFile() + " : " + contentType);
                            if ((contentType != null && contentType.startsWith(IMAGE_MIME_TYPE_PREFIX))) {
                                return new URL(BLANK_IMAGE_LOC).openConnection();
                            } else {
                                return super.openConnection(url, proxy);
                            }
                        }
                    };
                }

                return null;
            }
        });

        Application.launch();
    }
}

示例备注

该示例使用以下概念:

示例仅探测文件名以确定内容类型,而不是连接到URL的输入流。虽然探测输入流将是一种更准确的方法来确定url所连接的资源是否实际上是图像,但探测流的效率稍差,因此所提供的解决方案会提高效率的准确性。

提供的解决方案仅演示http协议所服务的位置,而不是https协议所服务的位置。

提供的解决方案使用sun.net.www.protocol.http.Handler类,它可能在Java 9中不公开(因此解决方案可能不适用于Java 9)。

urlStreamHandlerFactory是JVM的全局设置,因此一旦设置,它将保持这种状态(例如,将忽略任何java.net.URL连接的所有图像)。

示例解决方案返回一个空白(透明)图像,该图像通过网络加载。为了提高效率,可以从类路径而不是通过网络将图像作为资源加载。

您可以返回空连接,而不是连接到空白图像,如果这样做,Web视图代码将开始向控制台报告空指针异常,因为它没有获得它期望的url连接,并且用x图像替换所有图像以显示图像丢失(我不会真的推荐一种返回空连接的方法)。

答案 1 :(得分:4)

 public URLStreamHandler createURLStreamHandler(String protocol) {
     if ("http".equals(protocol)) { 
         return new URLFortuneHandler(); 
     }
     else return null;
 }
}

public class URLFortuneHandler extends sun.net.www.protocol.http.Handler {
    protected URLConnection openConnection(URL url) throws IOException {
        String file = url.getFile();
        int mid= file.lastIndexOf(".");
        String ext = file.substring(mid+1,file.length());        
        if ("jpg".equals(ext) || "png".equals(ext)) 
            return somethinghere;
        else 
            return super.openConnection(url);
    }    
}