4

I have a content type that accepts a PDF document as a file attachment. I have a bunch of entries that currently have no attachment, but I have the files for each entry and need to associate the files with each of their respective entries.

Currently, all of those files are stored in public://publications, so they're already in the public file path where they should be, I just need to "hook them up".

Rather than hack this with Ruby which I would normally do, I'd like to kick the bad habit and use the Drupal API. I've looked at the following articles:

..but haven't been able to really wrap my head around it.

Curious if others have dealt with this situation and what they've done to address it. Thanks.

UPDATE

I've got the files copying as they should be. However, I'm not encountering an error, and the error happens during the node_save call.

Here is the error:

PDOException: SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry '' for key 'uri': INSERT INTO {file_managed} (filesize, status, timestamp) VALUES (:db_insert_placeholder_0, :db_insert_placeholder_1, :db_insert_placeholder_2); Array
(
    [:db_insert_placeholder_0] => 0
    [:db_insert_placeholder_1] => 1
    [:db_insert_placeholder_2] => 1330491978
)
 in drupal_write_record() (line 6975 of /var/www/website/drupal-7.4/includes/common.inc).

And here is the code.

$node = node_load($bib_value->nid);

$file = new stdClass();
$file->filename = basename($filepath);
$file->filepath = $filepath;
$file->filemime = file_get_mimetype($filepath);
$file->filesize = filesize($filepath);
$file->uid = 1;
$file->status = FILE_STATUS_PERMANENT;
$file->uri = $filepath;
$file = file_copy($file,'public://publications',FILE_EXISTS_REPLACE);

// THIS IS A PROBLEM LINE
$node->field_publication_attachment[LANGUAGE_NONE] = $file;

node_save($node);

If I comment out the line labeled THIS IS A PROBLEM LINE then no error occurs, but that obviously isn't desirable because that means it's completing but without attaching my file to the node! Help!

SOLUTION

$node = node_load($bib_value->nid);

$file = new stdClass();
$file->filename = basename($filepath);
$file->filepath = $filepath;
$file->filemime = file_get_mimetype($filepath);
$file->filesize = filesize($filepath);
$file->uid = 1;
$file->status = FILE_STATUS_PERMANENT;
$file->uri = $filepath;
$file->display = 1;
$file->description = '';
$file = file_copy($file,'public://publications',FILE_EXISTS_REPLACE);

$node->field_publication_attachment[LANGUAGE_NONE][] = (array)$file;

node_save($node);

Needed to set display and description on $file as well as cast $file as an array when adding it to the attachment field. All worked smoothly after that.

2 Answers 2

5

I am currently working on the exact same thing, except using photos. If you click my profile name, you will see a series of questions related to learning how to do what you are asking to do.

I was able to easily accomplish the code to loop through all the files in my folder and add them to my nodes.

$file = new stdClass();
$file->filename = basename($local_path);
$file->filepath = $local_path;
$file->uri = $local_path;
$file->filemime = $mime;
$file->filesize = filesize($local_path);

// Set this at the very beginning to correspond to USER you want posting items.
$file->uid = $uid; 
$file->status = FILE_STATUS_PERMANENT;
file_save($file);

$images[] = array(
'fid' => $file->fid,
'alt' => $page_data['title'],
'title' => $page_data['title']
);
3
  • Did you run into any PDO issues, namely Integrity constraint violation: 1048 Column fid cannot be null? Feb 29, 2012 at 3:26
  • I did - see the added source code above. Calling 'file_save' will return the object with $file->fid properly filled out based on the insert into the database. Notice my images array now can properly use $file->fid so that, on node_save($node) you should not get that error. Later in the code $images is assigned to $node->files like this: $node->field_product_images[LANGUAGE_NONE] = $images; yours would be $node->my_file_field[LANGUAGE_NONE] = $my_files_array. Note, your file field may need different attributes. Use devel to see what fields need populating. You wont need alt and title fields.
    – blue928
    Feb 29, 2012 at 4:59
  • I updated my post with a new error message, this time referring to the uri. Thanks for your help. Feb 29, 2012 at 5:16
5

Another way of doing it:

$entity = entity_load($id);
$data = file_get_contents($localpath);
$destination = file_create_filename(basename($localpath), file_default_scheme() . '://yourdir/' );
$file = file_save_data($data, $destination);
$entity->field_attachment[LANGUAGE_NONE][] = (array)$file;
$entity->save();
1
  • The next time I need to do something similar I will try this. It's very short and concise. Apr 27, 2012 at 14:26

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.