Saving nodes with a filefield

1.7k views Asked by At

I'm in the progress of creating a bulk upload function for a Drupal site. Using flash I'm able to upload the files to a specific url that then handles the files. What I want to do, is not just to upload the files, but create a node of a specific type with the file saved to a filefield that has been setup with CCK. Since these are audio files, it's important that filefield handles the files, so addition meta data can be provided with the getid3 module.

Now I've looked through some of the code as I wasn't able to find an API documentation, but it's not clear at all how I should handle this. Ideally I could just pass the file to a function and just use the data returned when saving the node, but I haven't been able to find that function.

If any one has experience with this I would apreciate some pointers on how to approach this matter.

3

There are 3 answers

2
Henrik Opel On BEST ANSWER

I had to do something similar some weeks ago and ended up adapting some functionality from the Remote File module, especially the remote_file_cck_attach_file() function. It uses the field_file_save_file() function from the filefield module, which might be the function you're looking for.

In my case, the files are fetched from several remote locations and stored temporarily using file_save_data(). Attaching them to a CCK filefield happens on hook_nodeapi() presave, using the following:

public static function attachAsCCKField(&$node, $filepath, $fieldname, $index=0) {
  // Grab the filefield definition
  $field = content_fields($fieldname, $node->type);
  $validators = array_merge(filefield_widget_upload_validators($field), imagefield_widget_upload_validators($field));
  $fieldFileDirectory = filefield_widget_file_path($field);
  // This path does not necessarily exist already, so make sure it is available
  self::verifyPath($fieldFileDirectory);
  $file = field_file_save_file($filepath, $validators, $fieldFileDirectory);
  // Is the CCK field array already available in the node object?
  if (!is_array($node->$fieldname)) {
    // No, add a stub
    $node->$fieldname=array();
  }
  $node->{$fieldname}[$index] = $file;
}

$filepath is the path to the file that should be attached, $fieldname is the internal name of the filefield instance to use within the node and $index would be the 0 based index of the attached file in case of multiple field entries.

The function ended up within a utility class, hence the class syntax for the verifyPath() call. The call just ensures that the target directory is available:

public static function verifyPath($path) {
  if (!file_check_directory($path, FILE_CREATE_DIRECTORY)) {
    throw new RuntimeException('The path "' . $path . '" is not valid (not creatable, not writeable?).');
  }
}

That did it for me - everything else happens on node saving automatically.

I have not used the getid3 module yet, so I have no idea if it would play along with this way of doing it. Also, I had no need to add additional information/attributes to the filefield, so maybe you'd have to put some more information into the field array than just the file returned by field_file_save_file(). Anyways, hope this helps and good luck.

1
Grayside On

You might want to look at Image FUpload if you need a look at integrating the flash upload.

To push the files on to another server while still handling them through Drupal sounds a little like the CDN space, maybe look at the behavior in the CDN or CDN2 projects?

If you find a clear solution please come back and post it!

0
Jeremy French On

I have done something whith imagefield which worked, I think the structure has to be right otherwise it won't work. It took a lot of trial and error. This is is what I populated the imagefield with.

$image['data'] =array(
            'title' => $media_reference_attributes->getNamedItem("source")->value,
            'description' => $description,
            'alt' => "",);
$image['width'] = $width;
$image['height'] = $height;
$image['mimetype'] = $mime_type
$image['uid'] = 1;
$image['status'] = 1;
$image['fid'] = $fid;
$image['filesize'] = $file->filesize;
$image['nid'] = $id;
$image['filename'] = $url;
$image['timestamp'] = $file->timestamp;
$image['filepath'] = $file_path;

Hope this is of some help.