3

I'm trying to automatically add prefixes to uploaded file names so they can later be processed by non-drupal scripts. I want to do that while the user is uploading files during creation/editing of a node.

To do that I am using hook_file_validate($field) where I check if the file is correct and then using $field->destination I define a new file name.

Surprisingly my issue lies in getting context to generate the proper file name (nid of the node,nid of the parent group, or info from other fields). When I upload a file, only part of the website is reloaded by javascript and hook_file_validate is triggered before hook_form_alter . Whene it is triggered I have no access to any data that would tell me where am I.

So far I have tried:

$_REQUEST['destination']

while defined (not a typo) when the whole form is loaded, it is undefined when the file field of the form is reloaded

$_GET['nid']

again - undefined

arg(0); arg(1); arg(2);

returns file ajax field_quest_file which is not very usefull

I can access uid but it is not enough for me to create unique file names.

  • 1
    Files can be uploaded to nodes that have not yet been created so there won't necessarily be an nid at all, at least not at the point the file is uploaded. What about adding an additional submit handler to the form and doing the renaming in there once you know the node has been created? – Felix Eve Apr 23 '14 at 14:57
  • Felix, the node belongs to a group so as a naming convention I want to use group_id+user_id+filename.I keep your option in mind but it will make my life complicated as I will get files with the same names which will be renamed by drupal, which will lead to issues with processing by server side scripts. I want the files to verified, processed and plotted while the user uploads them and before he submits the whole node. – Pawel G Apr 23 '14 at 15:15
4

Following on from my comment suggesting you do this in an additional submit handler something like this should work:

Add the new submit handler:

function misc_form_alter(&$form, &$form_state, $form_id) {
  if($form_id == 'YOUR_CONTENT_TYPE_node_form') {
    $form['actions']['submit']['#submit'][] = 'rename_files';
  }
}

And then in the new submit handler:

function rename_files($form, &$form_state) {

  $node = $form_state['node'];

  global $user;

  // Loop over the uploaded files. Be sure to re-name field_files to the name of 
  // your file field.
  foreach($node->field_files[LANGUAGE_NONE] as $item) {

    // Load the file object
    $file = file_load($item['fid']);

    // To set the destination first remove the filename from the stream wrapper 
    // URI.
    $destination = str_replace($file->filename, '', $file->uri);

    // Modify this line to the name of your group field.
    $group = $node->field_group[LANGUAGE_NONE][0]['value'];

    // And then append the group, uid and put the filename back on the end.
    $destination .= $group.$user->uid.$file->filename;

    // And finally rename the file.
    file_move($file, $destination);
  }

}
  • I see one issue here. If drupal renames the file (so there are no 2 files with the same name) will the $file->filename change or will the change only be for $file->uri. Your script assumes that both will be renamed. As the original file name is important for me (for verification and plotting), if only uri gets renamed your code might actually do the trick for me. – Pawel G Apr 23 '14 at 16:02
  • 1
    @PawelG The URI will already have been passed through file_create_filename() to make sure it's unique, so filename and the filename part of uri will both be the same – Clive Apr 23 '14 at 16:51
  • Exactly like Clive said. There is also a third argument that can be passed into file_move that controls what happens when the destination file already exists. – Felix Eve Apr 24 '14 at 7:59
1

Instead of renaming the files I used a different approach and change their destination folder.

I do it from the level of hook_form_alter where I have full access to POST/GET arguments and the values in other fields of the form.

function myModule_form_alter(&$form,&$form_state,$form_id){
    switch($form_id){
        case 'nodetype_node_form':
            //prepare whatever prefix you want
            //in my case gid/uid/
            $dest_folder = _make_destination_folder($form);
            //findout which file will be added next
            //the form is rebuild each time a file is uploaded
            $delta = form['field_files'][LANGUAGE_NONE]['#file_upload_delta'];
            //instead of renaming files just change the destination folder
            form['field_files'][LANGUAGE_NONE][$delta]['#upload_location'] = 'private://'.$dest_folder;
            break;
    }
}

This way files end up in an unique, non random and predictable place before the node is even saved. A bonus of this approach is that I will have the files sorted in folders based on group and user

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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