This can be a bit tricky, there are a few steps to get right. First create and save the node, then add the file to the node as a second pass. Here's an example implementation.
/**
* Add a file to a field on a node
* @param int $nid node ID to add the content to
* @param string $field_name the machine name of the field to add to
* @param string $filedata the raw binary data as a string
* @param optional boolean is the attachment an image (should image validation
* be performed)
*/
function mymodule_addfile($nid, $field_name, $filedata, $is_image = FALSE) {
$node = node_load($nid);
$field = content_fields($field_name, $node->type);
// Load up the appropriate validators
$validators =
filefield_widget_upload_validators($field),
if ($is_image) {
$validators = array_merge(
$validators,
imagefield_widget_upload_validators($field)
);
}
// Where do we store the files?
$tmp_files_path = file_directory_temp()."/$file_name";
$files_path = filefield_widget_file_path($field);
// Put the file in the temp folder
$ret = file_put_contents($tmp_files_path,$filedata);
unset($filedata);
if ($ret === FALSE) {
watchdog('mymod_error',"Could not write $nid ($file_name) to temp: $tmp_files_path");
drupal_set_message("Could not write $nid ($file_name) to temp: $tmp_files_path", 'error');
return FALSE;
}
$path = $files_path.'/'.$file_name;
// Create the file object
$file = field_file_save_file($tmp_files_path, $validators, $path);
if ($file == 0) {
watchdog('mymod_error',"Failed to save file $file_name");
drupal_set_message("Failed to save file $file_name",'error');
return FALSE;
}
// Apply the file to the field
$node->{$field_name}[0] = $file;
node_save($node);
return TRUE;
}
A variation on the bottom works too, just assign the result to the file field.
function _fhi_add_existing_file($file_drupal_path, $uid=1, $status=FILE_STATUS_PERMANENT) {
$fs = filesize($file_drupal_path);
$res = db_query("SELECT fid FROM files WHERE filepath = '%s' AND filesize = '%s'", $filepath, $fs);
$fid = db_fetch_array($res);
if ($fid) {
//drupal_set_message("$filepath already found. fid: $fid");
$fid = $fid['fid'];
return field_file_load($fid);
} else {
$file=(object)array(
'filename' => basename($file_drupal_path),
'filepath' => $filepath,
'filemime' => file_get_mimetype($file_drupal_path),
'filesize' => $fs,
'uid' => $uid,
'status' => $status,
'timestamp' => time()
);
drupal_write_record('files',$file);
return field_file_load($file_drupal_path);
}
}
This code drawn from memory and without interpreter (I've got too much time on my hands this morning) so be wary of typos I may have introduced. As with anything, not responsible for death of poodles as a result of the use of this code.