java 具有HTML内容的JTextPane中的file://URI方案不起作用

tktrz96b  于 2023-01-01  发布在  Java
关注(0)|答案(1)|浏览(161)

我在应用程序的文件夹中创建了一个图像缓存,并编写了下载图像和检查图像是否存在的代码。
但是,由于某种原因,我不能在src属性中使用它们。
我读过这两篇文章:
jEditorPane handling local images
Display images using JEditorPane
然而,在第一个问题中,OP说他使用了另一种方法来设置图像源,这不适合我的情况。
第二篇文章假设file://模式应该可以不带任何技巧地开箱即用,但不知何故,它在我的情况下不起作用。
A尝试将正斜杠替换为反斜杠,将空格替换为%20并保持原样,尝试file://和file:///前缀-没有任何效果。我可以使用ImageIO读取我的文件,但JTextPane HTML渲染器找不到它们,因此屏幕上只有错误占位符。
图像路径的示例:

file:///D:/My%20Documents/NetBeansProjects/XMessenger/cache/http%3A%2F%2Fpopov654.pp.ru%2Fcopybox%2Fphoto.jpg

下面是代码:

private int last_width = 0;
private HashMap<String, Image> imgCache = new HashMap<String, Image>();

private void createTestMessageContent(final JComponent parent) {

    String html = "Some <i>text</i><br>And more,<br>And more...<br>And more...<br>And more...<br>And more...<br>And more...<br>" + 
            "<img src=\"http://popov654.pp.ru/copybox/photo.jpg\" width=\"390\" height=\"260\">" +
            "<img src=\"http://popov654.pp.ru/copybox/DSCN2155.jpg\" width=\"390\" height=\"260\">" +
            "<img src=\"http://popov654.pp.ru/copybox/DSCN2157.jpg\" width=\"390\" height=\"260\">";
    html = "<div style=\"padding: 0px; font-size: 14px; font-family: Tahoma\">" + html + "</div>";

    final String orig_html = html;

    Matcher m = Pattern.compile("((<img src=\"[^\"]+\")( width=\"\\d+\")?( height=\"\\d+\")?([^>]*>)\\s*)+").matcher(orig_html);
    while (m.find()) {
        String str = m.group();
        Matcher m2 = Pattern.compile("src=\"([^\"]+)\"").matcher(str);
        while (m2.find()) {
            File f = new File("cache");
            if (!f.exists()) {
                f.mkdir();
            }
            String src = m2.group(1);
            String cached_name = src.replaceAll("/", "%2F").replaceAll(":", "%3A");
            File img = new File("cache/" + cached_name);
            System.err.println(img.getAbsolutePath());
            if (!img.exists()) {
                InputStream in = null;
                BufferedInputStream b_in = null;
                FileOutputStream fileOutputStream = null;
                try {
                    in = new URL(src).openStream();
                    b_in = new BufferedInputStream(in);
                    fileOutputStream = new FileOutputStream("cache/" + cached_name);
                    byte dataBuffer[] = new byte[1024];
                    int bytesRead;
                    while ((bytesRead = in.read(dataBuffer, 0, 1024)) != -1) {
                        fileOutputStream.write(dataBuffer, 0, bytesRead);
                    }
                    //Files.copy(in, Paths.get("cache/" + cached_name), StandardCopyOption.REPLACE_EXISTING);
                } catch (IOException ex) {
                    ex.printStackTrace();
                } finally {
                    try {
                        in.close();
                        b_in.close();
                        fileOutputStream.close();
                    } catch (IOException ex) {}
                }
            } else {
                html = html.replaceFirst("src=\"" + src + "\"", "src=\"file:///" + img.getAbsolutePath().replaceAll("\\\\", "/").replaceAll(" ", "%20") + "\"");
            }
        }
    }

    final String cached_html = html;

    html = html.replaceAll("(<img src=\"[^\"]+\")( width=\"\\d+\")?( height=\"\\d+\")?([^>]*>)", "<a href=\"#\" style=\"display: inline-block; margin-right: 10px\">$1 width=\"390\" height=\"260\" hspace=\"2\" vspace=\"8\" border=\"0\"$4</a>");
    System.out.println(html);

    msgContent.setText(html);
    addHyperlinkListener(msgContent);

    //msgContent.setMinimumSize(new Dimension(msgContent.getWidth(), msgContent.getPreferredSize().height + 20));
    //setMinimumSize(new Dimension(getWidth(), msgContent.getPreferredSize().height + 160));
    setPreferredSize(new Dimension(getWidth(), msgContent.getPreferredSize().height + 148));
    
    initImages();

    updateSize();

    content2.addComponentListener(new java.awt.event.ComponentListener() {

        @Override
        public void componentResized(ComponentEvent e) {
            int new_width = ((JPanel)e.getSource()).getWidth();
            if (new_width != last_width) updateImages(cached_html);
            last_width = new_width;
        }

        @Override
        public void componentMoved(ComponentEvent e) {}

        @Override
        public void componentShown(ComponentEvent e) {}

        @Override
        public void componentHidden(ComponentEvent e) {}

    });
}

private void initImages() {
    HTMLDocument doc = (HTMLDocument) msgContent.getStyledDocument();
    Element[] imgs = getElementsByTagName(HTML.Tag.IMG, doc);
    for (Element img: imgs) {
        Element a = img.getParentElement();
        try {
            String src = (String) img.getAttributes().getAttribute(HTML.Attribute.SRC);
            System.out.println("src=" + src);
            System.out.println();

            Image image = null;
            if (!src.startsWith("http://") && !src.startsWith("https://")) {
                String path = src;
                if (src.startsWith("file:///")) {
                    path = path.substring(8).replaceAll("%20", " ");
                }
                image = ImageIO.read(new File(path));
            } else {
                image = ImageIO.read(new URL(src));
            }
            imgCache.put(src, image);
        } catch (Exception ex) {
            ex.printStackTrace();
        }
    }
}

private void updateImages(String orig_html) {
    int width = XMessengerApp.getMainWindow().getMessagePaneWidth() - 108;

    double default_ratio = 16f / 9;

    int img_width = (int) (width * 0.65);
    int img_height = (int) ((double)img_width / default_ratio);
    int margin = (int) (width * 0.005);

    String html = orig_html;
    Matcher m = Pattern.compile("((<img src=\"[^\"]+\")( width=\"\\d+\")?( height=\"\\d+\")?([^>]*>)\\s*)+").matcher(orig_html);
    while (m.find()) {
        String str = m.group();
        String str_new = str;
        String[] img_strs = str.split(">\\s*<");
        if (img_strs.length > 1) {
            System.err.println("Image series found of " + img_strs.length + " images");
        }
        if (img_strs.length > 1) {
            img_width = (int)((width - margin * img_strs.length) / img_strs.length * 0.95);
            img_height = (int)((double)img_width / default_ratio);
        }
        for (int i = 0; i < img_strs.length; i++) {
            if (i > 0) img_strs[i] = "<" + img_strs[i];
            if (i < img_strs.length-1) img_strs[i] = img_strs[i] + ">";

            Matcher m2 = Pattern.compile("src=\"([^\"]+)\"").matcher(img_strs[i]);
            m2.find();
            String src = m2.group(1);

            double ratio = default_ratio;
            if (imgCache.containsKey(src)) {
                Image img = imgCache.get(src);
                ratio = (double) img.getWidth(null) / img.getHeight(null);
                //System.out.println("Aspect ratio: " + ratio);
            }
            if (img_strs.length == 1) {
                img_height = (int)((double)img_width / ratio);
            } else {
                img_width = (int)((double)img_height * ratio);
            }
            //System.out.println("Src: " + src);

            String replace = img_strs[i].replaceAll("(<img src=\"[^\"]+\")( width=\"\\d+\")?( height=\"\\d+\")?([^>]*>)", "<a href=\"#\" style=\"display: inline-block; margin-right: " + margin + "px\">$1 width=\"" + img_width + "\" height=\"" + img_height + "\" hspace=\"" + margin + "\"vspace=\"8\" border=\"0\"$4</a>");
            str_new = str_new.replaceFirst(img_strs[i], replace);
        }
        if (img_strs.length > 1) {
            str_new = "<div style=\"float: left; margin-left: -10px\">" + str_new + "</div>";
        }
        html = html.replaceFirst(str, str_new);
            
    }

    msgContent.setText(html);

}

private void updateSize() {
    try {
        Dimension d = msgContent.getPreferredSize();
        Rectangle r = msgContent.modelToView(msgContent.getDocument().getLength());
        d.height = r.y + r.height;
        msgContent.setPreferredSize(d);
        Dimension d2 = content2.getPreferredSize();
        d2.height = r.y + r.height + 200;
        content2.setPreferredSize(d2);
        JFrame topFrame = (JFrame) SwingUtilities.getWindowAncestor(this);
        topFrame.getContentPane().validate();
    } catch (Exception ex) {}
}
dw1jzc5e

dw1jzc5e1#

找到问题了。似乎我应该转义文件名中的%符号,将其替换为%25,但前提是我在URL字符串中使用该路径。当我使用File()处理该文件时,不需要使用File()

相关问题