JTextPane加载含HTML内容的file:// URI图片失败问题
图片缓存无法在JTextPane的HTML img标签中加载
我在应用目录中实现了图片缓存功能,已完成图片下载与存在性检测的代码开发,但无法在HTML的img标签src属性中使用本地缓存的图片。
我参考过两篇相关文章,但第一篇中提问者采用的图片源设置方法不适用于我的场景;第二篇文章指出file://协议应无需额外配置即可使用,但在我的场景中无效。
我尝试了替换正斜杠与反斜杠、将空格替换为%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) {} }
内容的提问来源于stack exchange,提问作者Alex654
相关产品推荐
相关产品推荐

