Posted On: September 17, 2015

I was working on a Drupal project in which I needed to provide downloadable vCards. I used a nice php vCard class by JeroenDesloovere.

The class sets the headers to force the vCard to download and not open up as text in your browser. When I was on my development environment, the vCard would prompt to download as expected. Once I pushed things to the production environment and turned Drupal page cache on, the vCards would open up as plain text in the browser.

Using Firebug to inspect the headers, I noticed that the Content-Type was set to text/html even though the vCard class specifically set the Content-Type to text/x-vcard.

Drupal vCard Cache

Notice the X-Drupal-Cache Hit? This made me think it was an issue with caching, especially since it didn't happen on my local environment where caching was turned off.

I'm triggering the download using hook_menu to provide a menu callback in which I call the download method from the vCard class. The download method sets the headers and returns the output of the generated vCard file. So in my callback, I just return the output of that method.

/**
 * Implements hook_menu()
 */
function mymodule_menu() {
  $items = array();
 
  $items['mymodule/%user/vcard'] = array(
    'title' => 'vCard',
    'access arguments' => array('access content'),
    'page callback' => 'mymodule_user_vcard_page',
    'page arguments' => array(1),
    'type' => MENU_CALLBACK,
  );
 
  return $items;
}
 
/**
 * Page callback for user vcards.
 */
function mymodule_user_vcard_page($user) {
  // load profile
  if ($profile = profile2_load_by_user($user, 'main')) {
 
    // get profile fields
    $field_name = field_get_items('profile2', $profile, 'field_name');
    $field_email = field_get_items('profile2', $profile, 'field_email');
    $field_direct_line = field_get_items('profile2', $profile, 'field_direct_line');
 
    $lastname = $field_name[0]['family'];
    $firstname = $field_name[0]['given'];
    $additional = $field_name[0]['middle'];
    $prefix = $field_name[0]['title'];
    $suffix = $field_name[0]['generational'];
    $email = $field_email[0]['email'];
    $phone = $field_direct_line[0]['value'];
 
    require_once __DIR__ . '/vendor/autoload.php';
 
    $vcard = new JeroenDesloovere\VCard\VCard();
 
    $vcard->addName($lastname, $firstname, $additional, $prefix, $suffix);
    $vcard->addEmail($email);
    $vcard->addPhoneNumber($phone, 'PREF;WORK');
 
    return $vcard->download();
  }
}

The problem here is return $vcard->download();. This will cause the Drupal cache hit with the incorrect headers.

The solution is very simple, just change that line to...

    ...
    print $vcard->download();
    exit();
  }
}

This will bypass the Drupal cache and use the correct headers that were set by the vCard class. Be sure to clear your Drupal cache after making this change. Now when I inspect the headers, they are what we would expect.

Drupal vCard No Cache

I was lucky to have figured this out quickly. This could have easily cost me more than an hour. I hope it saves you a lot of time!

Add new comment

Plain text

  • No HTML tags allowed.
  • Web page addresses and e-mail addresses turn into links automatically.
  • Lines and paragraphs break automatically.