FOP: как указать относительный путь к изображению src?

Это мой первый вопрос здесь, я надеюсь, что я делаю это правильно. Извините за мой плохой английский заранее :)

Я использую JSF 2.0 (Eclipse IDE) и пытаюсь создать несколько файлов PDF с помощью Apache FOP 1.0.

Мне удалось создать простые PDF-файлы с помощью инструкций на сайте Apache Fop, но я не могу вставить изображение из папка моего приложения. Моя структура папок такова: в моем приложении WebContent у меня есть (среди прочего) pdf_transform/xslt/transformFile.xsl и pdf_transform/xslt/logo.jpg

В transformFile.xsl у меня есть

<fo:block><fo:external-graphic src="url('logo.jpg')"/></fo:block>

но когда я нажимаю кнопку «showPDF» в своем сервлете, я получаю файл PDF без изображения (все остальное есть), и это сообщение в консоли:

СЕРЬЕЗНЫЙ: источник, который был возвращен из разрешения URI, не содержал InputStream для URI: logo.jpg 18 ноября 2010 г. 17:16:49 org.apache.fop.events.LoggingEventListener processEvent СЕРЬЕЗНЫЙ: изображение не найдено. URI: логотип.jpg. (Контекстная информация недоступна)

Я пытался использовать 'logo.jpg' вместо url('logo.jpg'), помещая изображение в разные места внутри папки WebContent и используя другую навигацию("./logo.jpg"), но это не сработало.

Он отлично работает, если я задаю абсолютный путь (например, «d:/fop/images/logo.jpg»), но мне нужны ресурсы в моем приложении.

Во время поиска я обнаружил, что это связано с fopFactory.setURIResolver() и/или userAgent.setBaseURL(). Пробовал что-то с этим, но не получилось.

Я новичок как в JSF, так и в FOP, и эта ситуация с изображением беспокоила меня довольно давно. Может ли кто-нибудь помочь мне с этим или хотя бы направить меня к какому-нибудь руководству о том, «как настроить FOP для использования относительного пути»?

РЕДАКТИРОВАТЬ: мне не нужны абсолютные пути, и приложение должно работать независимо от его местоположения на компьютере (для публикации). Мой поиск говорит мне, что это как-то связано с настройкой FOP, но я не знаю, как это сделать :)

Заранее спасибо.

P.S. Это метод, который вызывается для отображения PDF:

public void printExchangeRateList(ActionEvent event) {

    BufferedOutputStream output = null;

    FacesContext facesContext = FacesContext.getCurrentInstance();
    ExternalContext externalContext = facesContext.getExternalContext();
    HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();  

    String path = externalContext.getRealPath("/");


    try {

        response.reset();
        response.setHeader("Content-Type", "application/pdf");
        output = new BufferedOutputStream(response.getOutputStream(), 10240);

        File xsltfile = new File(path+"/pdf_transform/xslt/transformFile.xsl");

        FopFactory fopFactory = FopFactory.newInstance();
        FOUserAgent foUserAgent = fopFactory.newFOUserAgent();

        try {
            Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output);

            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer(new StreamSource(xsltfile));

            Source src = new DOMSource(makeXML()); // my method
            Result res = new SAXResult(fop.getDefaultHandler());

            transformer.transform(src, res);


        } finally {
            if (output != null) output.close();
            /*try {
                out.close();
            } catch (IOException e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }*/
        }

    } catch (Exception e) {
        // TODO Auto-generated catch block
    }

    facesContext.responseComplete();
}

person Nikola    schedule 18.11.2010    source источник


Ответы (3)


я нашел решение своей проблемы. Я думал, что пробовал это, но, кажется, тогда я сделал небольшую ошибку. Во всяком случае, со следующим кодом

FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
String basePath = externalContext.getRealPath("/");

FopFactory fopFactory = FopFactory.newInstance();
fopFactory.setBaseURL(basePath);
FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
foUserAgent.setBaseURL(fopFactory.getBaseURL());

Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, foUserAgent, output); // for some output

вы можете получить доступ к своим изображениям (и другим ресурсам) из вашего файла xslt, используя относительный путь, начиная с папки WebContent вашего приложения. В моем случае я могу получить доступ к logo.jpg следующим образом

<fo:external-graphic src="url('pdf_transform/xslt/logo.jpg')"/>

Мне потребовалось время, чтобы понять это, я не понимаю, почему в сети нет примеров с такими базовыми вещами (или я не могу их найти :)

Примечание. В FOP 2.0 нет метода setBaseURL(). Вместо этого вы передаете базовый URL-адрес в качестве параметра FopFactory.newInstance(). Многие другие установщики перемещены в FopFactoryBuilder.

person Nikola    schedule 21.11.2010

Если у вас есть доступ к веб-адресу изображений, вы также можете использовать его при создании отчетов, например, http://localhost/images/logo.jpg .

Но хотя у меня все еще были изображения локально на веб-сервере, я включил путь к приложению в XML-файл и использовал его следующим образом:

<xsl:variable name="base_path" select="base-path"/>
<xsl:variable name="logo" select="companies/company/logo"/>
<fo:external-graphic src="url({$base_path}{logo})"/>

Где структура XML может быть примерно такой:

<?xml version="1.0" encoding="UTF-8"?>
<base-path>/path/to/app/</base-path>
<companies>
  <company>
    <logo>images/company1.jpg</logo>
  </company>
  <company>
    <logo>images/company2.jpg</logo>
  </company>
</companies>
person DanneManne    schedule 18.11.2010
comment
Спасибо за Ваш ответ. Но это не то, что я ищу. Когда вы создаете xml, строка /path/to/app/ должна выглядеть примерно так: C:\Eclipse\workspace\myProject\.. и т. д. (если я правильно понял). Я делаю это приложение доступным для публикации, и все XML-данные и изображения, к которым я обращаюсь, должны быть связаны с областью приложения (извините, я не написал это явно в своем вопросе, я отредактирую его сейчас). - person Nikola; 19.11.2010

У меня была такая же проблема, и я попробовал это решение:

    FOUserAgent foUserAgent = fopFactory.newFOUserAgent();
    Request request = RequestCycle.get().getRequest();
    //sort of a hack to find the path to the files that are in /img folder.
    String baseUrl = request.getUrl().getProtocol()+"://"+request.getUrl().getHost()+":"+request.getUrl().getPort();  
    foUserAgent.setBaseURL(baseUrl);

Затем в XSL я использовал:

<fo:external-graphic src="/img/image.png" />

Чтобы проверить, работает ли это, вы должны увидеть изображение на protocol://link:port/img/image.png.

person fventura    schedule 24.12.2013