A Simple Pattern for Importing Images

Sep 25 2009

When migrating legacy sites into Drupal, one challenging issue is importing images. The CCK imagefield module is one of the most popular ways to store images in Drupal 6, and we at Palantir.net use it on all of our production sites. This short tutorial shows you how to write a quick importer that can copy existing images into Drupal's files directory and then attach the image to a node using the CCK filefield. You might use this strategy within a larger importer (perhaps driven by Drupal's Batch API).

Here's a quick pattern that I've now successfully used to transform an existing image into a Drupal-controlled image stored in a CCK field. <!--break--> First, we need a function that takes the real path of the image to be imported, copies the image into Drupal, and then returns the necessary metadata:

<?php
/**
 * Import an image.
 *
 * @param $file_path The FULL PATH to the original file, e.g. /foo/bar/my_image.jpg
 */
function util_import_image($file_path) {
  global $user;

  // Make sure the existing image exists and is readable.
  if (!is_readable($file_path)) {
    watchdog('cma_import', 'Image not readable: %file', array('%file' => check_plain($file_path)));
  }

  // Original filename (without the path)
  $filename = basename($file_path);

  // Modify this if you want to save somewhere other than sites/default/files
  $dest = file_directory_path();

  // Create a new object for image metadata
  $asset = new stdClass();
  $asset->filename = $filename;

  // Copy the file and, if successful, create the metadata object.
  if (file_copy($file_path, $dest, FILE_EXISTS_REPLACE)) {
    $asset->uid = $user->uid;
    $asset->filepath = $dest . '/' . $asset->filename;
    $asset->filemime = file_get_mimetype($asset->filename);
    $asset->timestamp = time();
    $asset->status = 1;
    drupal_write_record('files', $asset);
  }

  // Only return an asset if it saved correctly. We return
  // an array because that is what CCK uses.
  return isset($asset->fid) ? (array)$asset : NULL;
}
?>

Now that we have this function, we can add an image to an existing node (one that has a filefield image) by doing something like this:

<?php
// Create a new node.
$node = stdClass();
$node->title = 'foo';
// ... Set more node properties

// Add the image.
$node->field_my_image[] = util_import_image($path);

// Save the node.
node_save($node);
?>

The important line is this one:

<?php
$node->field_my_image[] = util_import_image($path);
?>

This adds the image. You need to change the name of the field to suit your CCK fields. For example, if you have a CCK image named article_image, then the line above would become:

<?php
$node->field_article_image[] = util_import_image($path);
?>

That is the key to storing CCK file fields, though.

That is all there is to it. Where do you go if you get frustrated? Try using the devel module's dpm() function to dump the node, and inspect its contents. That may show you what is going wrong. You may also want to look at other CCK modules to see how data is handled.

Thanks to agentrickard and heyrocker for giving me the crucial tips to make this work.

(Comments will be back online shortly)