0

Im using FOP version 2.1. I have a xsl fo template where i want to show images:

 <xsl:variable name="ImagePath" select="defaultImageUrl"/>
 <fo:external-graphic src="{$ImagePath}" content-width="scale-down-to-fit" width="100%"/>

Some images have a webadress like so:

https://upload.wikimedia.org/wikipedia/commons/thumb/b/b1/Tulipa_biflora_UME.jpg/800px-Tulipa_biflora_UME.jpg

But other images come from my webserver from address like:

https://localhost:4200/api/download/image/?fixedPrice=true&amp;productId=1329&amp;fileId=1304

This responds to endpoint:

public ResponseEntity<byte[]> getFileAsResponseEntity(@RequestParam boolean fixedPrice, @RequestParam long productId, @RequestParam long fileId) throws IOException, SQLException {
    HttpHeaders headers = new HttpHeaders();
    FileDownload fileDownload = productService.getProductFile(productId, fileId, fixedPrice);
    headers.setCacheControl(CacheControl.noCache().getHeaderValue());
    String n = fileDownload.getFileName().toLowerCase();
    if (fileDownload.getFileTypeEnum().equals(FileTypeEnum.PICTURE) && (n.contains(".jpeg") || n.contains("jpg"))) {
        headers.setContentType(MediaType.IMAGE_JPEG);
    } else if (fileDownload.getFileTypeEnum().equals(FileTypeEnum.PICTURE) && (n.contains(".png"))) {
        headers.setContentType(MediaType.IMAGE_PNG);
    } else if (fileDownload.getFileTypeEnum().equals(FileTypeEnum.PICTURE) && (n.contains(".gif"))) {
        headers.setContentType(MediaType.IMAGE_GIF);
    }
    return new ResponseEntity<>(fileDownload.getByteArray(), headers, HttpStatus.OK);
}

Is there a way for fo:external-graphic to accept these 2 different urls? Or is there something additional i need to do for it to work, since currently when the image comes from the webserver, the the resulting pdf file does not have the image in it, only a white space.

EDIT: Here is the code that should make the XML to XSL to PDF:

 byte[] xsl = IOUtils.toByteArray(this.getClass().getResourceAsStream("/browserDocument.xsl"));
    byte[] xml = getBrowserDocument(filter, clientId, representId, ecatMain, showImage, language);
    InputStream inStr = this.getClass().getResourceAsStream("/fop.xml");
    FopFactory fopFactory = FopFactory.newInstance(new java.net.URI("."), inStr);
    ByteArrayOutputStream out = new ByteArrayOutputStream();

    Fop fop = fopFactory.newFop(MimeConstants.MIME_PDF, out);

    javax.xml.transform.Source xsltSrc = new StreamSource(new ByteArrayInputStream(xsl));

    TransformerFactory transformerFactory = TransformerFactory.newInstance();
    Transformer transformer = transformerFactory.newTransformer(xsltSrc);

    String xmlStr = new String(xml, "UTF-8");
    xmlStr = xmlStr.replaceAll("<", "<");
    xmlStr = xmlStr.replaceAll(">", ">");

    javax.xml.transform.Source src = new StreamSource(new ByteArrayInputStream(xmlStr.getBytes("UTF-8")));
    Result res = new SAXResult(fop.getDefaultHandler());

    transformer.transform(src, res);

    return out.toByteArray();

I keep getting error message in the log files:

2019-01-30 16:07:48.300 ERROR 8424 --- [https-jsse-nio-8087-exec-3] org.apache.fop.apps.FOUserAgent          : Image not found. URI: https://localhost:4200/api/efront/secure/download/product/image/?fixedPrice=false&productId=2823&fileId=1756. (No context info available)

It seems like it is calling the URL, but it is not getting the actual image from it. Maybe some issue with the image headers or the FOUseragent is getting blocked?

Marko Taht
  • 1,448
  • 1
  • 20
  • 40
  • Do you have any condition at xslt level, based on what you are passing url value to **fo:external-graphic** ? – Vebbie Jan 30 '19 at 11:40
  • mm... XSL just places the URL into the fo:external-graphic. What url to use is done inside the server before it reaches the part for xsl. defaultImageUrl comes from a model where the choise is already made. – Marko Taht Jan 30 '19 at 11:45
  • Right. Then there is no change require at xslt level to these 2 urls to be accepted. What's the exception/validation bug are you facing here ? – Vebbie Jan 30 '19 at 11:50
  • if image comes from the webserver it is not shown on the resulting pdf document. I think the issue might actually be the & – Marko Taht Jan 30 '19 at 11:51
  • It might be the relative path issue. (Make sure the images exist in your webserver). Can you share your **FopFactory** code ? – Vebbie Jan 30 '19 at 11:56
  • @Vebbie edited question. – Marko Taht Jan 30 '19 at 12:06
  • try this : ``. See also https://stackoverflow.com/questions/54427499/image-not-found-for-background-image-attribute-of-block-container/54428956#54428956 – potame Jan 30 '19 at 12:28
  • @potame: If it's a recent version of Apache FOP, you don't have to put the image path inside url(...). (Though it isn't mentioned what version is being used) – Vebbie Jan 30 '19 at 12:33
  • Took a bit to find it. but v 2.1 is in use. – Marko Taht Jan 30 '19 at 12:43
  • Resetting the image cache might help here. The image cache can be cleared like this: `fopFactory.getImageManager().getCache().clearCache();` – Vebbie Jan 30 '19 at 12:56
  • DIdnt help. Still only the images that are not from the webserver are shown. – Marko Taht Jan 30 '19 at 13:41

1 Answers1

0

Well, implementing all above possible logic and seeing your code, I think URIResolver would help getting out of this as below:

Add it to your code : fopFactory.setURIResolver(new ResolveURIForWebServer());

import javax.xml.transform.Source;
import javax.xml.transform.TransformerException;
import javax.xml.transform.URIResolver;

public class ResolveURIForWebServer implements URIResolver {

@Override
public Source resolve(String href, String baseURI) throws TransformerException {
    Source source = null;
    try {
        // CONVERT IMAGE TO INPUTSTREAM
        source = new StreamSource(InputStream);

    } catch (Exception e) {

    } finally {

    }
    return source;
}
}

Hope it helps.

Vebbie
  • 1,669
  • 2
  • 12
  • 18
  • Also it seems tobe causing a "java.lang.RuntimeException: javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: ..." – Marko Taht Jan 30 '19 at 14:52
  • You can validate the certificate by following this https://stackoverflow.com/questions/9619030/resolving-javax-net-ssl-sslhandshakeexception-sun-security-validator-validatore and if you can try again. – Vebbie Jan 31 '19 at 10:11
  • This thing didnt work out. so i took the longer route. Since the images are on the websever i wrote a piece of code that gets the file location in the filesystem and passes that to the xsl. – Marko Taht Jan 31 '19 at 11:01