ФОП: как указать относительный путь изображения SRC? - PullRequest
9 голосов
/ 18 ноября 2010

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

Я использую 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 без изображения (все остальное есть), и это сообщение в консоли:

SEVERE: источник, который был возвращен из резолюции URI не содержит InputStream для URI: logo.jpg 18 ноября, 2010 17:16:49 org.apache.fop.events.LoggingEventListener processEvent SEVERE: изображение не найдено. URI: logo.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();
}

Ответы [ 3 ]

11 голосов
/ 22 ноября 2010

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

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 .

2 голосов
/ 18 ноября 2010

Если у вас есть доступ к веб-URL для изображений, вы также можете использовать его при создании отчетов, например, 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>
0 голосов
/ 24 декабря 2013

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

    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" />

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

...