File Upload, overwriting every time I am using the Migrate module, and I need to upload a CSV file before every migration run.  I've created a module that allows me to upload a file.

My first step was to make sure I had the logic correct for overwriting a file, so I have the following code:

function migrate_htmlfiles_form_alter(&amp;$form, &amp;$form_state, $form_id) {

if ($form_id == 'migrate_ui_dashboard_form') {
  $form['fldset'] = array(
   "#type"        =&gt; "fieldset",
   "#title"       =&gt; "CSV to Import",
   "#collapsible" =&gt; "TRUE",
   "#collapsed"   =&gt; "FALSE",
   "#weight"      =&gt; "-98",
 );
$form['fldset']['csv_file'] = array(
   "#type"   =&gt; 'managed_file',
   "#title"  =&gt; t('Choose a file'),
   "#upload_location" =&gt; 'private://user_migration',
   "#upload_validators" =&gt; array(
      "file_validate_extensions" =&gt; array('csv'),
   ),

 );

$form['fldset']['actions'] = array(
   "#type"    =&gt; 'submit',
   "#value"   =&gt; t('Uploady'),

 );

}

return $form;

}


That creates the file upload widget etc.

The following is what I do upon form submission:

 function migrate_htmlfiles_form_submit($form, &amp;$form_state) {

  $file = file_load($form_state['values']['csv_file']);
  //TODO: rename file to user_migrate.csv
  $file-&gt;status = FILE_STATUS_PERMANENT;
  $file-&gt;replace = FILE_EXISTS_REPLACE;
  file_save($file);
}


The file uploads fine, and then when I refresh the form, and do another upload, that works but the file is not overwritten, but is incremented.
What you're describing is the expected behaviour for a managed_file widget. If you dig through the functions you eventually get to file_managed_file_save_upload(), which is responsible for actually saving the file. 

That function calls file_save_upload() without the 4th parameter, which is $replace. 

Since the default for that parameter is FILE_EXISTS_RENAME, file_save_upload() has no choice but to use in that context.

When you refresh the page, the original file that was uploaded has not been cleared up; in fact it won't be until the temp file cron job runs. So Drupal is "correctly" ensuring that the original file doesn't exist, because the managed file field is telling it to rename, not replace, files.