file_save_upload

Versions
4.6
file_save_upload($source, $dest = 0, $replace = FILE_EXISTS_RENAME)
4.7
file_save_upload($source, $dest = false, $replace = FILE_EXISTS_RENAME)
5
file_save_upload($source, $dest = FALSE, $replace = FILE_EXISTS_RENAME)
6
file_save_upload($source, $validators = array(), $dest = FALSE, $replace = FILE_EXISTS_RENAME)
7
file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME)

Saves a file upload to a new location.

The file will be added to the {file} table as a temporary file. Temporary files are periodically cleaned. To make the file a permanent file, assign the status and use file_save() to save the changes.

Parameters

$source A string specifying the filepath or URI of the uploaded file to save.

$validators An optional, associative array of callback functions used to validate the file. See file_validate() for a full discussion of the array format.

$destination A string containing the URI $source should be copied to. Defaults to "temporary://".

$replace Replace behavior when the destination file already exists:

  • FILE_EXISTS_REPLACE: Replace the existing file.
  • FILE_EXISTS_RENAME: Append _{incrementing number} until the filename is unique.
  • FILE_EXISTS_ERROR: Do nothing and return FALSE.

Return value

An object containing the file information if the upload succeeded, FALSE in the event of an error, or NULL if no file was uploaded. The documentation for the "File interface" group, which you can find under Related topics, or the header at the top of this file, documents the components of a file object. In addition to the standard components, this function adds:

  • source: Path to the file before it is moved.
  • destination: Path to the file after it is moved (same as 'uri').

Related topics

▾ 8 functions call file_save_upload()

file_managed_file_save_upload in modules/file/file.module
Given a managed_file element, save any files that have been uploaded into it.
hook_prepare in modules/node/node.api.php
This is a hook used by node modules. It is called after load but before the node is shown on the add/edit form.
locale_translate_import_form_submit in includes/locale.inc
Process the locale import form submission.
system_theme_settings in modules/system/system.admin.inc
Form builder; display theme configuration for entire site and individual themes.
update_manager_install_form_submit in modules/update/update.manager.inc
Handle form submission when installing new projects via the update manager.
upload_node_form_submit in modules/upload/upload.module
Save new uploads and store them in the session to be associated to the node on upload_save.
user_validate_picture in modules/user/user.module
_file_test_form_submit in modules/simpletest/tests/file_test.module
Process the upload.

Code

includes/file.inc, line 1080

<?php
function file_save_upload($source, $validators = array(), $destination = FALSE, $replace = FILE_EXISTS_RENAME) {
  global $user;
  static $upload_cache;

  // Return cached objects without processing since the file will have
  // already been processed and the paths in _FILES will be invalid.
  if (isset($upload_cache[$source])) {
    return $upload_cache[$source];
  }

  // Make sure there's an upload to process.
  if (empty($_FILES['files']['name'][$source])) {
    return NULL;
  }

  // Check for file upload errors and return FALSE if a lower level system
  // error occurred. For a complete list of errors:
  // @see http://php.net/manual/en/features.file-upload.errors.php
  switch ($_FILES['files']['error'][$source]) {
    case UPLOAD_ERR_INI_SIZE:
    case UPLOAD_ERR_FORM_SIZE:
      drupal_set_message(t('The file %file could not be saved, because it exceeds %maxsize, the maximum allowed size for uploads.', array('%file' => $_FILES['files']['name'][$source], '%maxsize' => format_size(file_upload_max_size()))), 'error');
      return FALSE;

    case UPLOAD_ERR_PARTIAL:
    case UPLOAD_ERR_NO_FILE:
      drupal_set_message(t('The file %file could not be saved, because the upload did not complete.', array('%file' => $_FILES['files']['name'][$source])), 'error');
      return FALSE;

    case UPLOAD_ERR_OK:
      // Final check that this is a valid upload, if it isn't, use the
      // default error handler.
      if (is_uploaded_file($_FILES['files']['tmp_name'][$source])) {
        break;
      }

    // Unknown error
    default:
      drupal_set_message(t('The file %file could not be saved. An unknown error has occurred.', array('%file' => $_FILES['files']['name'][$source])), 'error');
      return FALSE;
  }

  // Build the list of non-munged extensions.
  // @todo: this should not be here. we need to figure out the right place.
  $extensions = '';
  foreach ($user->roles as $rid => $name) {
    $extensions .= ' ' . variable_get("upload_extensions_$rid",
    variable_get('upload_extensions_default', 'jpg jpeg gif png txt html doc xls pdf ppt pps odt ods odp'));
  }

  // Begin building file object.
  $file = new stdClass();
  $file->uid      = $user->uid;
  $file->status   = 0;
  $file->filename = file_munge_filename(trim(basename($_FILES['files']['name'][$source]), '.'), $extensions);
  $file->uri      = $_FILES['files']['tmp_name'][$source];
  $file->filemime = file_get_mimetype($file->filename);
  $file->filesize = $_FILES['files']['size'][$source];

  // Rename potentially executable files, to help prevent exploits.
  if (preg_match('/\.(php|pl|py|cgi|asp|js)$/i', $file->filename) && (substr($file->filename, -4) != '.txt')) {
    $file->filemime = 'text/plain';
    $file->uri .= '.txt';
    $file->filename .= '.txt';
  }

  // If the destination is not provided, use the temporary directory.
  if (empty($destination)) {
    $destination = 'temporary://';
  }

  // Assert that the destination contains a valid stream.
  $destination_scheme = file_uri_scheme($destination);
  if (!$destination_scheme || !file_stream_wrapper_valid_scheme($destination_scheme)) {
    drupal_set_message(t('The file could not be uploaded, because the destination %destination is invalid.', array('%destination' => $destination)), 'error');
    return FALSE;
  }

  $file->source = $source;
  // A URI may already have a trailing slash or look like "public://".
  if (substr($destination, -1) != '/') {
    $destination .= '/';
  }
  $file->destination = file_destination($destination . $file->filename, $replace);
  // If file_destination() returns FALSE then $replace == FILE_EXISTS_ERROR and
  // there's an existing file so we need to bail.
  if ($file->destination === FALSE) {
    drupal_set_message(t('The file %source could not be uploaded because a file by that name already exists in the destination %directory.', array('%source' => $source, '%directory' => $destination)), 'error');
    return FALSE;
  }

  // Add in our check of the the file name length.
  $validators['file_validate_name_length'] = array();

  // Call the validation functions specified by this function's caller.
  $errors = file_validate($file, $validators);

  // Check for errors.
  if (!empty($errors)) {
    $message = t('The specified file %name could not be uploaded.', array('%name' => $file->filename));
    if (count($errors) > 1) {
      $message .= theme('item_list', array('items' => $errors));
    }
    else {
      $message .= ' ' . array_pop($errors);
    }
    form_set_error($source, $message);
    return FALSE;
  }

  // Move uploaded files from PHP's upload_tmp_dir to Drupal's temporary
  // directory. This overcomes open_basedir restrictions for future file
  // operations.
  $file->uri = $file->destination;
  if (!move_uploaded_file($_FILES['files']['tmp_name'][$source], $file->uri)) {
    form_set_error($source, t('File upload error. Could not move uploaded file.'));
    watchdog('file', 'Upload error. Could not move uploaded file %file to destination %destination.', array('%file' => $file->filename, '%destination' => $file->uri));
    return FALSE;
  }

  // Set the permissions on the new file.
  drupal_chmod($file->uri);

  // If we are replacing an existing file re-use its database record.
  if ($replace == FILE_EXISTS_REPLACE) {
    $existing_files = file_load_multiple(array(), array('uri' => $file->uri));
    if (count($existing_files)) {
      $existing = reset($existing_files);
      $file->fid = $existing->fid;
    }
  }

  // If we made it this far it's safe to record this file in the database.
  if ($file = file_save($file)) {
    // Add file to the cache.
    $upload_cache[$source] = $file;
    return $file;
  }
  return FALSE;
}
?>
Login or register to post comments
 
 

All source code and documentation on this site is released under the terms of the GNU General Public License, version 2 and later. Drupal is a registered trademark of Dries Buytaert.