I am using this in a multipage form and have got it working fine. What I haven't been able to figure out is how to dynamically rename/name the file.
eg userid=2 submits image myimage.jpg. I want to save it as 2_myimage.jpg but am having no luck.
when I try
$filename = $user->uid."_".$form_state['storage'][2]['photo_upload']
$fid1 = upload_element_save($filename, $dest_path, FILE_EXISTS_RENAME);

it gives me an error like "recoverable fatal error: Object of class stdClass could not be converted to string in..."

Comments

alan d.’s picture

Title: dynamic naming of file » Prefixing filename with {user}.uid: A dynamic renaming example
Status: Active » Postponed (maintainer needs more info)

I haven't run the code, but the following function should work. Let me know if it works. I haven't a test environment at the moment.

<?php
/**
 * Saves an uploaded file
 *
 * @param object $file File object
 * @param string $dest destination directory to move the file to
 * @param int $replace files move action
 * @param string $presetname Imagecache preset to perfrom on the uploaded image.
 * @param bool $delete_original A flag to tell the function how to handle
 *   the existing file when it is deleted or replaced. This is used to
 *   prevent the status flag being set to temperory when the file is still used
 *   by the system somewhere else. For example, if you are saving a new
 *   node revision, with a new file, you would want to ensure that this is
 *   set to FALSE if the old image is still valid for some other revision.
 * @return int The {files}.fid or 0
 */
function upload_element_save_rename(&$file, $dest = 0, $replace = FILE_EXISTS_RENAME, $presetname = FALSE, $delete_original = TRUE) {
  global $user;
  $fid = 0;
  if (is_object($file)) {
    $base = file_directory_path();
    if (strstr($dest, $base) === FALSE) {
      $dest = $base .'/'. ltrim($dest, '/');
    }
    
    file_check_directory($dest, 1);
    if (!property_exists($file, 'submit_action')) {
      $file->submit_action = UPLOAD_ELEMENT_NONE; 
    }
    switch ($file->submit_action) {
      case UPLOAD_ELEMENT_NONE:
        $fid = $file->fid;
        break;
      case UPLOAD_ELEMENT_DELETE:
        if ($delete_original) {
          _upload_element_delete($file->fid);
        }
        break;
      case UPLOAD_ELEMENT_REPLACE:
        if ($delete_original) {
          _upload_element_delete($file->original_fid);
        }
        // fall through
      case UPLOAD_ELEMENT_NEW:
        $uploaded = FALSE;
        if ($presetname) {
          // If using imagecache preset, get imagecache to rename it
          $destination = file_create_filename($user->uid .'_'. $file->filename, $dest);
          if (upload_element_imagecache_action($presetname, $file->filepath, $destination)) {
            $file->filepath = $destination;
            // we need to update the name as well
            $path_parts = pathinfo($destination);
            $file->filename = $path_parts['filename'];
            $uploaded = TRUE;
          }
        }
        if (!$uploaded) {
          // No imagecache preset or if this failed, use Drupal to rename it
          $uploaded = file_move($file, $dest .'/'. $user->uid .'_'. $file->filename, $replace);
        }
        if ($uploaded) {
          $file->status = FILE_STATUS_PERMANENT;
          // Clear PHP stat cache in case filesize has changed.
          clearstatcache();
          if ($file_size = @filesize($file->filepath)) {
            $file->filesize = $file_size;
          }
          drupal_write_record('files', $file, 'fid');
          $fid = $file->fid;
          // Imagecache may need flushing if using the same filepath.
          if (function_exists('imagecache_image_flush')) {
            imagecache_image_flush($file->filepath);
          }
        }
        else {
          drupal_set_message(t('Error occured while saving the image!'), 'error');
        }
        break;
    }
  }
  // This cleans up the session by flushing old values.
  upload_element_clean_session();
  
  return $fid;
}

?>

It is only the section after "case UPLOAD_ELEMENT_NEW:" that has changed.

The two points of interest are the imagecache call:

<?php
        if ($presetname) {

          // If using imagecache preset, get imagecache to rename it using the prefix
          $destination = file_create_filename($user->uid .'_'. $file->filename, $dest);

          // apply and move the image
          if (upload_element_imagecache_action($presetname, $file->filepath, $destination)) {

            // Update the filepath if required
            // we need to update the filename as well
            $file->filepath = $destination;
            $path_parts = pathinfo($destination);
            $file->filename = $path_parts['filename'];
            $uploaded = TRUE;
          }
        }
?>

This is only applicable to images when imagecache preset is given.

If this fails / or if it is ignored, the we use Drupal to move and rename:

<?php
        if (!$uploaded) {
          // The file object is updated during the move, so no need to update name/path
          $uploaded = file_move($file, $dest .'/'. $user->uid .'_'. $file->filename, $replace);
        }
?>

Finally, replace the upload_element_save() call with the upload_element_save_rename() call.

Anonymous’s picture

Status: Postponed (maintainer needs more info) » Closed (fixed)

I'm impressed. Worked great. Exactly what I wanted. Thanks for the speedy response.