7.x file.inc file_save(stdClass $file)

Saves a file object to the database.

If the $file->fid is not set a new record will be added.


$file: A file object returned by file_load().

Return value

The updated file object.

See also



Related topics

13 calls to file_save()
EntityCrudHookTestCase::testFileHooks in modules/simpletest/tests/entity_crud_hook_test.test
Tests hook invocations for CRUD operations on files.
FileFieldTestCase::createTemporaryFile in modules/file/tests/file.test
Creates a temporary file, for a specific user.
FileSaveTest::testFileSave in modules/simpletest/tests/file.test
file_copy in includes/file.inc
Copies a file to a new location and adds a file record to the database.
file_field_presave in modules/file/file.field.inc
Implements hook_field_presave().

... See full list


includes/file.inc, line 612
API for handling file uploads and server file management.


function file_save(stdClass $file) {
  $file->timestamp = REQUEST_TIME;
  $file->filesize = filesize($file->uri);

  // Load the stored entity, if any.
  if (!empty($file->fid) && !isset($file->original)) {
    $file->original = entity_load_unchanged('file', $file->fid);

  module_invoke_all('file_presave', $file);
  module_invoke_all('entity_presave', $file, 'file');

  if (empty($file->fid)) {
    drupal_write_record('file_managed', $file);
    // Inform modules about the newly added file.
    module_invoke_all('file_insert', $file);
    module_invoke_all('entity_insert', $file, 'file');
  else {
    drupal_write_record('file_managed', $file, 'fid');
    // Inform modules that the file has been updated.
    module_invoke_all('file_update', $file);
    module_invoke_all('entity_update', $file, 'file');

  // Clear internal properties.
  // Clear the static loading cache.

  return $file;


ph0enix’s picture

Replaced to $file->save() in Drupal 8

texas-bronius’s picture

file_save() appends a few file object attributes like timestamp, filesize, but if you are simply sucking in a file from disk (like from a cron job or drush file load) and not working with an html form upload file field, you'll want to be add your own mimetype, like:

  $file = file_save((object)array(
    'filename' => $file_name,
    'uri' => $destination_uri,
    'status' => FILE_STATUS_PERMANENT,
    'filemime' => file_get_mimetype($destination_uri),

file_get_mimetype() does the magic. Note: Get $file_name from basename($destination_uri); which works on either uri or full path.

DrupalViator’s picture

The previous code works really well, thanks texas-bronius.

Here some code snippet if you have already files in the private or public directory, but not yet in the database (so file_load will not work):

$file_path = <your_path_to_existing_file>;
$dir = 'private://' . dirname($file_path); // or public:// or whatever you need
$file_name = basename($file_path);

$match = file_scan_directory($dir,  '/' . $file_name . '/', $options = array(), $depth = 0);

if (!empty($match)) {
  $file = reset($match); //if there is only one file
  $uri = $file->uri; // and so one, so you can extract filename and uri and use file_save() as shown above

  .... // proceed with code above


With this code-snippet you can find existing files within drupal directories and extract all needed information from the return array. Thus no new image is uploaded, instead we use existing files and only update/create database entries.