Forums

Displaying BLOB in chronoform

moshiani 14 Feb, 2012
Hi,

I've searched the forums but can't find the answer. I have a form using DB Record Loader event to display data from a MySQL database. I have an blob field in my table storeing the country map. I can't see an image element within chronoforms so I put the following custom code
<?php
echo $form->data['country']['map'];
?>

where 'country' is the model ID I used. But these just displays special characters and no image. Is there an easier way to display blob data type from MySQL within chronoform.

Thanks.
GreyHead 14 Feb, 2012
Hi moshiani,

I don't know the answer to this one :-( There was a thread with Fredrik and Chris last year about saving and restoring images to a database table and we never got the restore to work reliably. I'm sure that it is possible - just don't know how to do it.

Bob
nml375 14 Feb, 2012
Hi moshiani & Bob,
The proof-of-concept code worked well enough on my platform, however something did cause data corruption on Chris'. Unfortunately, the source for this corruption was never determined, and I could never reproduce it on my platform.

Nevertheless, I'll give you an outline to get started with:
Since you do use the BLOB datatype, there should'nt be any concerns with character set translations.

Next, the data in $form->data['country']['map'] would be the raw binary data; there's no easy way for your browser to actually know this is an image, and not some random text. Simply echo'ing the content will just show a lot of odd characters (as you described).

What you need to do, is instruct your browser to treat this as an image instead. This can be done in two ways;

The most common way is to use the <img> element, pointing to an external resource. In this case, you'd use a separate php-script to do the database-read, and set the appropriate headers to instruct your browser that it's really an image:
<?php
$index = intval($_GET['id']);
$db = new mysqli("example.tld", "user", "password", "database");
if ($db->connect_errno)
  die;
$query = $db->prepare("SELECT `map` FROM `jos_theTable` WHERE `id` = ? LIMIT 1");
$query->bind_param("i", $index);

$query->execute();
$query->bind_result($image);

if ($query->fetch())
{
  header("Content-Type: image/png");
  echo($image);
}
?>

You'd then add something like <img src="/path/to/script.php?id=X"> where X would be the id of the image to be displayed (I assumed it to be an integer here).

The other approach would be to use inline images. Keep in mind though, that this does not work for older browsers - especially IE 7 and older.
In this case, you'd have to base64-encode the image, and provide a modified value for the "src" attribute of the image element:
<img src="data:image/png;base64,<?php echo base64_encode($form->data['country']['map']); ?>"><


Worth mentioning though, is that the size for data-url's is rather limited; with opera maxing out somewhere around 4k, IE8 at 32k and firefox at 100k. Also, using base64 encoding adds an overhead of roughly 33%.

/Fredrik
moshiani 14 Feb, 2012
Thank you Fredrik for your detailed explanation, I gave up on using the blob earlier today and started using image files instead.

I had a question on this if you or anyone else can help. I have a chronform with a db loader event and after the on load event i've put some custom code to display the image depending on query paramater (in this example a 'code' which represents the country and the corresponding image is code.gif)
Below is the code I used:

<?php
$code=$form->data['code'];
?>
<script language="javascript">
var sStr = "images/maps/" + "<?php echo $code?>" + ".gif";
document.getElementById('map').src = sStr;
</script>

Am I putting this scipt in the wrong place or am I missing something because the image just doesn't change! (I have a blank placeholder image 'map' on the form)

I also tried the following code

<?php
$code=$form->data['code'];
$path = "images/maps/";
$ext= ".gif";
?>

<img src="<?php echo $path.$code.$ext ?>" alt="" />

But no luck, any suggestions would be greatly appreciated.
nml375 14 Feb, 2012
Hi moshiani,
Most likely, your javascript is evaluated before the entire page is loaded, and the DOM is not yet ready. Try using the DOMReady event instead:
<script language="javascript">window.addEvent("DOMReady", function() {
  var sStr = "images/maps/" + #<?php echo $form->data['code']; ?>" + ".gif";
  document.getElementById('map').src = sStr;
});
</script>


Or, even simpler, just write the correct url from the beginning?
<?php
if (!empty($form->data['code']))
{?>
<img id="map" src="images/maps/<?php echo $form->data['code']; ?>.gif" alt="Map"/>
<?php
} else
{?>
<img id="map" src="images/maps/placeholder.gif" alt="Placeholder map"/>
<?php
}?>


/Fredrik
moshiani 15 Feb, 2012
Thanks Fredrik for your suggestion. Sorry for this question but I'm still not getting the image populated based on the selected data from the from. I must be missing a step.

On my form, the first custom element is a drop down which on change triggers a reload of the same form with data from db (i've place a db record loader event on 'On Load', which extracts data from the country table based on the parameter (code) it receives). Below is code in the drop down custome element.

<img name "map" src="images/maps/blank.gif" width="100" height="100">

<?php
$options = array();
$options[] = "<option value=''>--?--</option>";
$db =& JFactory::getDBO();
$query = "
SELECT `code`, `name`
FROM `anl_chronoforms_data_country_form`
ORDER BY `name`;
";
$db->setQuery($query);
$data = $db->loadObjectList();
foreach ( $data as $d ) {
$options[] = "<option value='{$d->code}'>{$d->name}</option>";
}
?>

<select class="" id="countries" size="1" name="countries" onChange='OnChange(this.form.countries);'>
<?php echo implode("\n", $options); ?>
</select>

<SCRIPT LANGUAGE="javascript">
<!--
function OnChange(dropdown)
{
var myindex = dropdown.selectedIndex
var SelValue = dropdown.options[myindex].value
var baseURL = "index.php?option=com_chronoforms& chronoform=country_form&token="+SelValue
top.location.href = baseURL;
}
//-->
</SCRIPT>


As you can see the form is reloaded and I don't know where to place this code which updates the image based on the data on the form

({?>
<img id="map" src="images/maps/<?php echo $form->data['code']; ?>.gif" alt="Map"/>
<?php).

here is the link to the form: http://babybonbon.cloudaccess.net/index.php?option=com_chronoforms& chronoform=country_form

Any suggestion would be greatly appreciated thanks.
moshiani 15 Feb, 2012
I just wanted to add that if I just write the correct image path after the DB Record Loader Event I can see this when the page is refreshed.

<?php echo "images/maps/".$form->data['code'].".gif";?>

How I can do the same for an image?
nml375 15 Feb, 2012
Hi moshiani,
That code would be used instead of your placeholder image. Be aware that the snippet you copied is part of a conditional block (if-else), designed to show a placeholder if there was no content in $form->data['code'] (if the user didn't select a valid country).
So, replace this:
<img width="100" height="100" src="/images/maps/blank.gif">

With this:
<?php
if (!empty($form->data['code']))
{
  echo('<img width="100" height="100" src="/images/maps/' . $form->data['code'] . '.gif">');
} else
{
  echo('<img width="100" height="100" src="/images/maps/blank.gif">');
}
?>


/Fredrik
moshiani 15 Feb, 2012
Hi again,

I replaced theone line img code with the conditional statement. But the result is still the same 😟

Any other ideas?
nml375 15 Feb, 2012
Hi moshiani,
It would seem the empty-check in the conditional always fails; I'm not sure why.

I notice you used $form->data['country'][...] in your original post; Did you change the "Load under Model ID" setting later on?

/Fredrik
moshiani 15 Feb, 2012
Yes I removed the Model ID as I didn't think I needed it, also set 'Load Under Model ID' to no.
nml375 15 Feb, 2012
Hi moshiani,
Could you try modifying the code as below, for testing purposes?
<?php
if (!empty($form->data['code']))
{
  echo('Case is: true! Value of $form->data["code"]: ' . $form->data['code'] . "<br />\n");
  echo('<img width="100" height="100" src="/images/maps/' . $form->data['code'] . '.gif">');
} else
{
  echo('Case is: false! Value of $form->data["code"]: ' . $form->data['code'] . "<br />\n");
  echo('<img width="100" height="100" src="/images/maps/blank.gif">');
}
?>


/Fredrik
moshiani 15 Feb, 2012
Hi Fredrik,

The 'case is true' message and the code is correctly displayed on the page when a country is selected but the image still won't display.
nml375 15 Feb, 2012
Hi mishiani,
Just checked the form, and the code is properly generated. However, the URL for the image gives a "404 Not Found" error.

/Fredrik
nml375 15 Feb, 2012
Hi mishiani,
There's still a 404 Not found error. I did notice that the country code is in upper case (TZA), while your images have names in lower case (tza.gif). Web servers handle file names case sensitive, so that will have to be fixed.

You could either change the names of the files to uppercase names (TZA.gif), or use the strtolower() function to change the code name to lowercase:
<?php
if (!empty($form->data['code']))
{
  echo('<img width="100" height="100" src="/images/maps/' . strtolower($form->data['code']) . '.gif">');
} else
{
  echo('<img width="100" height="100" src="/images/maps/blank.gif">');
}
?>


/Fredrik
moshiani 16 Feb, 2012
Thank you so much for spotting this, it really saved the day!🙂
This topic is locked and no more replies can be posted.