Thursday, November 17, 2005

Missing images in CFDocument

I have seen huge no of postings on CF forum where CFDocument users have complained about seeing red-cross (or red-x ) for images . In this post, I would like to list the reasons why they happen and how they could be resolved .

Before we proceed with different cases of red-x, lets see in brief, how images are rendered in CFDocument.

During the processing of cfdocument tag, CF engine interprets/executes the content inside the cfdocument tag, creates html content out of it and renders it in the memory. While rendering this html content, if any image tag is found, a separate HTTP request is made to retrieve this image content. A separate HTTP request is necessary because image in the generated html can be local as well as remote. For Java geeks out there, we use URLConnection.getContent() to retrieve the image data. A red-x means that CFDocument was not able to retrieve the image.

Now lets see different scenarios one by one
  1. Image name has space in it. In CFMX 7.0, you can get red-x for images if the image file name has any space in it. For example if the image file name is "my picture.jpg", only a red-x will appear in the pdf/flashpaper. It happens because the url created for the image is not encoded. A workaround for this is to either use encoded url for the images i.e replace 'space' in the name with '%20' OR dont have spaces in the file name at all :). This bug has been fixed in Merrimack (Coldfusion 7.0.1). So if you are still on 7.0, upgrade :)

  2. If your server is behind firewall. As we mentioned earlier, CF server needs to send an HTTP request for the images. If the firewall prevents any outgoing connection from the server, CF will not be able to retrieve them and will show a red-x in place of them. You will need to setup your firewall in such a way that server can send an HTTP request to itself.

  3. If your server is behind a proxy. If Coldfusion server is connected to the external world using a proxy, then also CFDocument will not be able to load the images. This is because currently there is no way you can specify proxy configuration for CFDocument tag.
    Current solution to solve this is to define the following system properties for the JVM. You can specify these in "runtime/bin/jvm.config" if you are using standlone or on JRun server.

    -DproxySet=true -DproxyHost=[hostname] -DproxyPort=[port] -Dhttp.proxyHost=[hostname] -Dhttp.proxyPort=[port]

  4. If you are using HTTPS and your images do not appear in the pdf/flashpaper, you must ensure the following
    • CF server's certificate is trusted. In other words, certificate of the CA who issued the certificate for you, must be present in the trusted certificate store (runtime/lib/trustStore). You can use keytool to list/view/import/.. certificate in the certificate store.
      If CF is using a self signed certificate, CF's certificate must be present in the trustStore.
    • The certificate is valid and has not expired.
    • Host name of the server must match the host name to which the certificate was issued.

  5. If the resources on your webserver are protected using some kind of authentication like basic authentication or digest authentication, cfdocument can not retrieve those resources. That is because you can not provide any authentication information to cfdocument tag currently. This means that cfdocument can not retrieve images if it is protected using authentication and you will see a red-x. One solution for this is to replace all image urls with "file" urls.
    See this entry
    for more details on this workaround. The other solution is to write little java code to set a 'java.net.Authenticator'. I will post a separate entry for this.

  6. You get red-x for images and you have verified that its none of the above mentioned cases. Time to check the web server now. We have seen some cases where the web server is configured to allow requests only from a certain set of browsers (User agents to be precise) perhaps to prevent spiders and bots from overloading the server. When CFDocument creates a URLConnection for the image, it sends a "User-Agent" header, that looks like "User-Agent:Java/1.4.2_07", in the HTTP request. If the web server does not recognize "Java" user-agent, it returns a status code of 404 (resource not found) and hence the images can not be displayed. Solution for this case is to either change the configration for the web server or set your own user agent using the following system property on the JVM.
        -Dhttp.useragent="ColdFusion"
    You can give any name here as userAgent in place of "ColdFusion".

Hope this helps people in resolving isues related to missing images in CFDocument. In case you are getting a red-x even after verifying all the cases mentioned above, please let me know.

Related Entry :

30 comments:

Abdul said...

Hey Rupesh-

Welcome to blogging....Sorry for offtopic comment :)

-abdul

Anonymous said...

Hello,

We need assistance in creating a Socket Gateway. Do you have examples of the following:

1. A listener of a TCP/IP Socket
2. Passing data to listerner from a cfc
3. Handling response from listener

Thanks!
Richard

Rupesh Kumar said...

Hi Richard,
We ship the exactly same socket gateway sample that you looking for. You can check out the sample at [CF_installDir]/gateway/src/examples/socket/SocketGateway.java

You might also want to go through this doc on how to write an event gateway at
http://livedocs.macromedia.com/coldfusion/7/htmldocs/wwhelp/wwhimpl/common/html/wwhelp.htm?context=ColdFusion_Documentation&file=00001692.htm
Please let me know if you need any help.

Thanks,
Rupesh

Anonymous said...

Hey Rupesh. I linked to this entry from my blog. The one thing I'd add to your HTTPS entry is to clarify that the hostname used in the URL must match the name in the cert. You cannot use an IP or localhost or any other DNS/hostname/machinename.

Anonymous said...

Hi Rupesh

Thanks for this info - it was a life saver. My cfdocument code was broken on our staging server which was sharing a certificate as our production server. It would have worked fine in production, but we wouldn't have moved it there and I would have been out of a job !

Ram

Anonymous said...

Rupesh,
Your blog re: Missing images in CFDocument got me going in the right direction. I kept coming back to items 2 & 3 but my developement box was not behind a firewall or proxy. Then I realized that I was accessing a test website with the following url... http://testsite/. I have an entry in my hosts file for "testsite" but the server does not and, therefore, could not resolve the address. Adding the item to the server's hosts file did the trick. Thanks.
-Sam

Anonymous said...

Hi Rupesh!
We have a strange problme with cfdocument. Initially we used to get missing images with cfmx7. Then we upgraded it to cfmx 7.01 and applied the cumulative hotfix for it.
It seemed to resolve the problem for some time, but when we restarted the server the same problem of missing images occured.

This is happening for quite a sometime. After every restart we need to apply the hotfix again. Otherwise the images are not displayed.
There is no problem with proxy/firewall beacuse if we make cfhttp request to images the status is 200 OK.
What could be the problem?
Anything related to classpath?

Anonymous said...

Another problem with it is if you are loading in an image that is of bmp type. I generate a head sheet dynamically and display it in the cfdocument, the results are any image that is not jpg or gif display as red x

Rupesh Kumar said...

yes. Currently we support only certain type of images (gif, jpeg and png) inside CFDocument. Hopefully we will have the support for bmp and tiff images in the Scorpio release.

Rupesh Kumar said...

It seems weird that you need to apply the hotfix after every start of the server. how do you apply the hotfix? All you need to do is to put the hotfix jar in the 'update' directory.

- For Standalone it will be [cf install dir]/cfusion/lib/update.

- For J2EE installations it will be [deployed directory]/WEB-INF/cfusion/lib

Anonymous said...

My site has SSL and requires basic authentication. Is there any reason the need for authentication would be preventing my PDF from showing images? I've checked everything else.

Rupesh Kumar said...

Hi Mancho,
I dont think that basic authentication would have any effect on this.
Try this simple step to isolate the problem. Comment out the cfdocument tag so that your cfm has only plain cfm and html content. Ensure that you can see the entire content in the browser properly.
Please let me know if this works and you encounter the problem only with cfdocument.

Regards,
Rupesh

Anonymous said...

Regarding the comment from Mancho that was made on 2/13/2006, and the reply from Rupesh:

Rupesh (and others, elsewhere) wrote: "Try this simple step to isolate the problem. Comment out the cfdocument tag so that your cfm has only plain cfm and html content. Ensure that you can see the entire content in the browser properly."

If this test suceeds you may still have the red-X problem with your images. Q:Why? A:When you enter a site that requires authentication, subsequent requests to that domain work normally, however CFDOCUMENT will fail in it's attempt to retrieve the image via HTTP - because authentication is required and there is no way to pass userid & pwd using CFDOCUMENT. As far as I can tell, your images MUST reside at an address that DOES NOT REQUIRE authentication.

So, if the test described by Rupesh succeeds but you still have the red-X problem when using images in CFDOCUMENT, try again after moving your images to a site that does not use authentication.

Anonymous said...

Cfdocument and missing images.

We have an extra level of difficulty.

For secuurity reasons we are using using cfcontent to pull in an image. it works fine when viewing the page without cfdocument, but when the pdf is produced the image is missing.

any suggestions?

Thanks

Rupesh Kumar said...

How are you planning to use cfcontent to get the image and use it inside your page? can you post a code snippet or a sample page for me?

Anonymous said...

Hi Rupesh,

I want to reply to your last posting because I have a similar problem using CFCONTENT to serve images but CFDOCUMENT will not print them.

Here is how we display images in the page:

<img src="../logoexport.cfm?dlfilename=#urlEncodedFormat(thumbfilename)#">

In the LogoExport.cfm page we have:

<cftry>
<cfcontent type="image/jpg" file="#materials_thumb_directory##url.DLFilename#" deletefile="No">
<cfcatch type="Any">
<cfcontent type="image/jpg" file="#application.materials_thumb_directory##url.DLFilename#" deletefile="No">
</cfcatch>
</cftry>

We do this so we can keep certain images in non-web accessible directories for security reasons. However, as the previous post states, CFDocument will not print these images.

For the record, we have also tried ActivePDF and it will not print them either.

My thinking is that both of these apps pre-render the page in HTML but the IMG tag retains its CFM page as the SRC. When it's printed it's assuming all the CF processing is done and simply printing content when, in fact, all our IMG tags still need processed. Am I making sense?

Any ideas for a workaround?

Thanks!

Rupesh Kumar said...

It looks very strange to me.. I tried your example and it works fine at my end.
Here is what I tried

test.cfm
-----------
<cfdocument format="pdf">
some content
<cfset thumb="3.jpg">
<cfoutput>
<img src="image.cfm?filename=#urlEncodedFormat(thumb)#">
</cfoutput>
</cfdocument>
------------
image.cfm
------------
<cfset dire="C:/">
<cfcontent type="image/jpg" file="#dire##url.filename#" deletefile="No">

------------
I dont see any error and image comes up fine. Did you check other pointers that I mentioned in the post. Can you try my example on some other box and see if that works. I would also suggest you to take a look at the exception.log and error.log to see if there was any error there.

A simple workaround for you can be to use a file url for image directly in the page instead of going through logoexport.cfm.
Let me know how it goes.

Anonymous said...

I am in a distributed environment. Think that would have anything to do with the problem. IIS on one server, CFMX7 on the other.

Rupesh Kumar said...

Hi Joey,
You should check two things.
- check if your cluster has "sticky session" enabled? sticky session means that all the request in one session will go to the same server. cfchart will be a problem if you are not using sticky session.
- Try increasing the timeout value for cfchart images. Though this setting can not be changed from the admin page, you can do that easily by modifying <CFMX dir>/lib/webcharts3D.xml file. you should change minTimeout and maxTimeout value (in millisecond) to an appropriate value.

<server image="PNG" cache="Memory" minTimeout="5000" maxTimeout="30000"....
>
For more details on cfchart image expiration you can refer Prayank's blog

Rupesh

Anonymous said...

Nice catch. We have IIS authentication turned on on our intranet site and couldn't figure out those blasted red x's. We put the images in a different directory and now it works great. THANKS!

Anonymous said...

I'm having the same problem with cfchart and cfdocument in a cluster. sticky session are enabled and i have changed the timeout but it still doesn't work. I think the problem is in the way the server collects the images by making the url request. I believe no session information is being sent with the request causing this problem.

Anonymous said...

Great post...and I think I fall into situation 2 or 5.

I'm using cfcontent to display images from a BLOB field. It's not working on the client's server, but works fine on my laptop dev machine.

Is there an easy way to test issue #2? As it stands I can use CFCONTENT just fine for a standard HTML page, but in CFDOCUMENT is bombs (red x).

Where in IIS (win 2K) would I check for the user agent filtering you mention in issue 5?

Thanks in advance ;-)

Anonymous said...

Hey guys,

If you are calling to image files located locally on your machine you can simply call them using "file:///".

Example:
<img src="file:///#THIS.finalDir#/#qDetails.barcode#_vert.gif" />

This seems to work 100% (so far).

Anonymous said...

I have an odd problem that is happening on our DEV server 7.0.1 and our Production server 7.0.1. When displaying an image in the PDF it is SOMETIMES missing. Yet in the same PDF, the same image in a different section of the PDF - the image displays fine. Again this only happens to the first image, and only sometimes.

Very wierd...

Any ideas?

Anonymous said...

more info -

No red 'x' - just a blank space where the image SHOULD be.

Rupesh Kumar said...

I think the new hotfix for CFDocument that we have release might help.
Check my other post here

Anonymous said...

Hotfix didn't help. Resolved by setting the height="0" and width="0" in a img tag with that image name as the src. Then display the same image again, but using the correct sizes for height and width. Works 100% now - before maybe 60%.

Charlie Arehart said...

Folks reading this old (but great) entry should note that there is another useful solution to this problem, if they're on CF8 or above, in the new localurl attribute for CFDOCUMENT. If you know that the filenames you use in the img tags are indeed local to the server serving the page, adding localurl="yes" will tell CF not to try to use an HTTP request to find them to show in the CFDOCUMENT output. The default is no (I assume for backward compatibility). See the CF docs for info (or perhaps Rupesh may offer still more).

Anonymous said...

Thank a lot Todd, you rule!

LarryP said...

I have a CFM page that uses cfdocument to create a PDF on the server that includes an image file, and when I invoke the page it works great: the PDF has the image file in it. I'm using the localurl="yes" option and a relative path to the image file and it works great like that (CF9).

My problem is that I am cfincluding this CFM page in a CFC. When I do that, the PDF is generated as expected, but I get the red X instead of the image. While the CFC and the CFM are in the same path, they are not in the same folder, so I've tried every folder in the path to pull my image file from, thinking it was a path issue, but that hasn't panned out.

Any ideas? I've tried everything I can think of and am posting this as a last resort. I even tried omitting the localurl="yes" option and grabbing the image file as a separate http request, but get the same red x result.