I've successfully used Perl (via Embperl) to create a dynamically-generated vCard for employees, populating all the fields except for the photo. I can't get that working no matter what. (The code to generate a photo-less vCard works fine.)
According to the information I can find online, the image must be base64-encoded in the vCard itself. The vCard spec (I'm using 3.0) supports URL-linked images, but my iPhone won't link to them that way. So it's base64 or nothing.
Now, I know the base64-encoding works, because if use the code to just show an image...
[-
$photo = "/path/to/directory/".$employeeID.".jpg";
open($file, "<", $photo) || warn "Can't open $photo: $!\n";
#binmode $file;
$jpg = join('', <$file>);
$decoded = MIME::Base64::encode_base64($jpg);
$vcard_content = $decoded;
-]
<img src="data:image/jpeg;base64,[+ $decoded +]">
...then the photo shows up perfectly in my browser. (Someone suggested I needed binmode $file;
in there, but removing it seems to make no difference in the output.)
But if I include it in the vCard instead, the photo simply doesn't show up with the rest of the contact data:
$vcard_content = "BEGIN:VCARD\r";
$vcard_content .= "VERSION:3.0\r";
$vcard_content .= "N:".$v_last.";".$v_first.";".$v_middle.";;\r";
# etc.
$vcard_content .= "PHOTO;ENCODING=b;TYPE=JPEG:".$decoded."\r";
# etc.
$vcard_content .= "END:VCARD";
Am I mis-formatting the vCard data somehow?
After importing the vCard into OS X Contacts and exporting it again, then viewing the exported vCard with a text editor, I noticed that the first part of the base64-encoded image was there but the rest was not. The encoding stopped right where a whitespace (\r
apparently) character appeared in the encoded string.
So I removed all the whitespace characters from the base64 encoding before building the vCard:
$decoded = MIME::Base64::encode_base64($jpg);
$decoded =~ s/\s//g;
And now the photo imports correctly.