Drupal 6: Upload an image using the Forms API and attach it to a image/file field in a CCK node

In this tutorial I'll show you how to upload an image using the Forms API, create a new node, and attach the image to the CCK (filefield/imagefield) field. I wrote this code to work with the modules I primarily use for image processing: cck, filefield, imageapi, imagecache, imagefield, mimedetect, and transliteration.

After I installed those modules I created a new node type (admin/content/types/add) called "Image" and added a single imagefield field.

Image node fields

Next I created a custom module with a hook_menu() implementation:

<?php

// NOTE: this variable is used through the code,
// so I thought it would be better to put it in a constant
define('IMAGE_UPLOAD_CONTAINER', 'image_upload');

/**
 * Implements hook_menu()
 */
function helper_menu() {

  // create a blank array of menu items
  $items = array();

  // define page callback for upload form
  // NOTE: you'll want to restrict permission better [see: access arguments]
  $items['upload'] = array(
    'title' => t('Upload'),
    'description' => t('Upload'),
    'page callback' => 'drupal_get_form',
    'page arguments' => array('helper_page_callback_upload_form'),
    'access arguments' => array('access content'),
    'type' => MENU_CALLBACK,
  );

  // return menu items
  return $items;

}
?>

I defined the form function page callback:

<?php

/**
 * Implements page callback for upload form
 */
function helper_page_callback_upload_form() {

  // create an empty form array
  $form = array();

  // set the form encoding type
  $form['#attributes']['enctype'] = "multipart/form-data";

  // add a file upload file
  $form[IMAGE_UPLOAD_CONTAINER] = array(
    '#type' => 'file',
    '#title' => t('Upload an image'),
  );

  // add a submit button
  $form['submit'] = array(
    '#type' => 'submit',
    '#value' => 'Submit',
  );

  // return form array
  return $form;

}
?>

This page callback function results in the following form:

Image node form

Then I added the form validation and submit handler functions:

<?php

/**
 * Implements form validation handler
 */
function helper_page_callback_upload_form_validate($form, &$form_state) {

  // if a file was uploaded, process it.
  if (isset($_FILES['files']) && is_uploaded_file($_FILES['files']['tmp_name'][IMAGE_UPLOAD_CONTAINER])) {

    // validate file extension
    // NOTE: you can ellaborate on this code and add additional validation
    if ($_FILES['files']['type'][IMAGE_UPLOAD_CONTAINER] != 'image/jpeg') {
      form_set_error(IMAGE_UPLOAD_CONTAINER, 'Invalid file extension.');
      return;
    }

    // attempt to save the uploaded file
    $file = file_save_upload(IMAGE_UPLOAD_CONTAINER, array(), file_directory_path());

    // set error if file was not uploaded
    if (!$file) {
      form_set_error(IMAGE_UPLOAD_CONTAINER, 'Error uploading file.');
      return;
    }

    // set files to form_state, to process when form is submitted
    $form_state['storage'][IMAGE_UPLOAD_CONTAINER] = $file;

  }
  else {
    // set error
    form_set_error(IMAGE_UPLOAD_CONTAINER, 'Error uploading file.');
    return;
  }

}

/**
 * Implements form submit handler
 */
function helper_page_callback_upload_form_submit($form, &$form_state) {

  // create new node object
  $new_node = (object) array(
    'type' => 'image',
    'uid' => $GLOBALS['user']->uid,
    'name' => $GLOBALS['user']->name,
    'title' => t('YOUR NODE TITLE'),
    'status' => 1,
    'field_image' => array(
      (array) $form_state['storage'][IMAGE_UPLOAD_CONTAINER],
    ),
  );

  // save node
  node_save($new_node);

  // clear form storage, to allow form to submit
  $form_state['storage'] = array();

  // redirect user, set message, etc!

}

?>

After using the form to upload an image, the following node was created:

New image node