Возможно ли / как встраивать и получать доступ к файлам HTML в JAR?

Я несколько заблокирован прямо сейчас: я написал довольно сложное настольное приложение Java (без апплета/веб-приложения!), У которого есть собственное «Руководство пользователя». Это руководство состоит из нескольких файлов HTML и JPG. Это руководство отображается в «Меню справки» в моем приложении с помощью JEditorPane.

Все идет нормально. Это работает очень хорошо, пока я запускаю программу с Eclipse. Как только я создаю версию развертывания в виде исполняемого файла jar (который заворачивается в .exe с помощью launch4j), HTML «Просмотрщик» не может отобразить руководство пользователя (изображения отсутствуют).

Я понимаю, почему это происходит, но я понятия не имею, как это исправить/обойти.

Мое приложение загружает свои ресурсы (файлы свойств, значки и т. д.) через getClass().getResource(). Примеры:

this.setIconImage(new ImageIcon(getClass().getResource("/images/dialog-question.png")).getImage());

stream = new BufferedInputStream(MABIUpdater.class.getResourceAsStream("/settings.properties"));

Как я уже говорил, это работает очень хорошо (запуск приложения из Eclipse ИЛИ в виде обернутого исполняемого файла или runnable-jar.

Итак, я тоже попытался получить доступ к своим HTML-руководствам:

File manual = new File(getClass().getResource("/manual/help.html").toURI());

jEditorPane.setPage(manual.toURI().toURL());

Это НЕ работает. Запустив программу через Eclipse, я вижу руководство, но с отсутствующими изображениями. Запуская его через jar/exe, я получаю пустой фрейм.

Так есть ли какой-нибудь «трюк» о том, как этого добиться? Я предполагаю, что одной из проблем является сама HTML-страница, потому что она не может получить доступ к связанным изображениям в этой банке. Вот действительно небольшой пример HTML-файла, который не работает (отсутствует изображение):

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Frameset//EN" "http://www.w3.org/TR/html4/frameset.dtd">
<html lang="de">
    <head>
        <title>Manual</title>
    </head>
    <body>
        <h1>Example: </h1>
        <p>fubar</p>
        <img style="display: block; text-align: center;" src="../manual/img/Shot01.png" width="666" height="644" border="0" alt="Bildtext">
        <p><a href=\"http://www.google.com/\">blablubb</a></p>
    </body>
</html>

Я надеюсь, что моя проблема ясна, и у кого-то есть идея;).

Изменить: все необходимые файлы HTML и изображения находятся в файле JAR/пути к классам. (просто чтобы было понятнее)


person Ulathar    schedule 26.08.2013    source источник


Ответы (2)


File manual = new File(getClass().getResource("/manual/help.html").toURI());

Вот где это идет не так. Java не может создать объект File из embedded-resource

Сохраните его как URL и используйте для setPage(..).


Что касается более общей проблемы.

HTML из файла Jar, который связывает ресурсы (например, CSS или изображения) с помощью относительных ссылок, будет работать нормально.

E.G.

В этом примере загружается HTML (который имеет относительную ссылку на изображение) из Jar.

import javax.swing.*;
import java.net.URL;

class ShowHtml {

    public static void main(String[] args) {
        final String address =
            "jar:http://pscode.org/jh/hs/object.jar!/popup_contents.html";
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                try {
                    URL url = new URL(address);
                    JEditorPane jep = new JEditorPane(url);
                    JFrame f = new JFrame("Show HTML in Jar");
                    f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
                    f.add(new JScrollPane(jep));
                    f.pack();
                    f.setSize(400,300);
                    f.setLocationByPlatform(true);
                    f.setVisible(true);
                } catch(Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }
}

Снимок экрана

JEditorPane, отображающий Jar'd HTML

HTML

Загружаемый HTML.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//EN">
<!--       
 *        Copyright (C) 1997  Sun Microsystems, Inc
 *                    All rights reserved.
 *          Notice of copyright on this source code 
 *          product does not indicate publication. 
 * 
 * RESTRICTED RIGHTS LEGEND: Use, duplication, or disclosure by 
 * the U.S. Government is subject to restrictions as set forth 
 * in subparagraph (c)(1)(ii) of the Rights in Technical Data
 * and Computer Software Clause at DFARS 252.227-7013 (Oct. 1988) 
 * and FAR 52.227-19 (c) (June 1987).
 *
 *    Sun Microsystems, Inc., 2550 Garcia Avenue,
 *    Mountain View, California 94043.
 *
-->
<HTML>
<HEAD>
<TITLE>
Editing Project Attributes
</TITLE>
</HEAD>
<BODY BGCOLOR="#ffffff">
<IMG SRC="images/popup_icon.gif" width="24" height="24"> <b>Popup Window</b>
<p>
Popup windows appear near the location from which they are
activated.  They are not contained in frames and thus
cannot be resized or moved by the user.  Popups are
dismissed by clicking anywhere in the help viewer.
<p>
Popup windows can be activated by clicking on a text object, 
graphic object, or JComponent button.  All three examples are
included in this demo.
<p>
<A HREF="popup_contents2.html">More...</A>
</body>
</html>

E.G. 2

Для динамически созданного HTML JRE вероятно будет использовать местоположение файла класса в качестве предполагаемого местоположения HTML. Но чтобы развеять все сомнения, мы можем указать элемент base в файле head.

import javax.swing.*;

class HtmlUsingBase {

    public static void main(String[] args) {
        final String htmlContent =
            "<html>" +
            "<head>" +
            "<base href='http://www.gravatar.com/'>" +
            "</head>" +
            "<body>" +
            "<h1>Image path from BASE</h1>" +
            "<img src='avatar/a1ab0af4997654345d7a9" +
            "49877f8037e?s=128&d=identicon&r=PG'" +
            " width='128' height='128'>" +
            "</body>" +
            "</html>";
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                JLabel label = new JLabel(htmlContent);
                JOptionPane.showMessageDialog(null, label);
            }
        });
    }
}

Снимок экрана

введите здесь описание изображения

person Andrew Thompson    schedule 26.08.2013
comment
вау, это было быстро, большое спасибо, ребята! Оба ответа мне очень помогли / решили проблему, но Эндрю Томпсонс был более подробным, поэтому я выбрал его ответ. не могу проголосовать, потому что я здесь новенькая :(. - person Ulathar; 26.08.2013
comment
Рад, что смог быть полезен. :) - person Andrew Thompson; 26.08.2013

Когда у вас есть URI, вы превращаете его в файл, а затем обратно в URI, а затем в URL. Вы могли бы добиться большего успеха, просто превратив URI в URL

person Theodore Norvell    schedule 26.08.2013