I've got a managed file field in a form like this:

$form['source_file'] = array(
  '#type' => 'managed_file',
  '#title' => t('Source File'),
  '#default_value' => isset($data['source_file']) ? $data['source_file'] : 0,
  '#upload_validators' => array(
    'file_validate_is_image' => array(),
    'file_validate_extensions' => array('png gif jpg jpeg'),
  '#upload_location' => 'public://imagemerge/merge/',
  '#required' => FALSE,

My submit function looks like this so far:

function imagemerge_merge_submit($form, &$form_state) {
  $source_file_fid = $form_state['values']['data']['source_file'];
    if ($source_file_fid != 0) {
      $source_file = file_load($source_file_fid);
      $source_file->status = FILE_STATUS_PERMANENT;
    } else {
      //some logic to determine previous fid?
      //and then a call to file_delete()

The docs for Forms API under managed_file say that it is up to the module to call file_delete. How do I know when and which file to delete?

3 Answers 3


Ok I solved this but it will be different for each type of form. The form I was adding this managed_file upload to is actually the image effect form. (image_effect_form(), I had to do some form_altering to add my submit function.) My goal was to add a new image effect that allows placing a source file onto the destination image.

What I finally did was compare the $form_state variables in the submit function for the following actions:

  1. uploading a file when none was previously there
  2. removing a file and submitting no file
  3. removing a file and uploading a new file

For this particular form I came up with the following variables:

$new_fid = $form_state['values']['data']['myformfile'];
$old_fid = $form_state['image_effect']['data']['myformfile'];

Once I got what the new FID is and what the old FID was It was trivial to put together some logic that deletes the file at the appropriate place. The problem is that this isn't universal logic that works for every type of form that has a managed_file in it. There didn't seem to be a standard way to get what the old file FID was. I found it for this specific form but for the next time I do a managed_file I'll have to examine $form_state again and find out if/where the old file FID is stored.

My code for the submit function is below. I also added some logic for the file_usage table.

$source_file_new_fid = $form_state['values']['data']['source_file'];
$source_file_old_fid = $form_state['image_effect']['data']['source_file'];

if ($source_file_new_fid != 0) {
  $source_file = file_load($source_file_new_fid);
  $source_file->status = FILE_STATUS_PERMANENT;
  file_usage_add($source_file, 'imagemerge', 'image_style', $form_state['image_style']['isid']);

if ($source_file_old_fid != 0) {
  $del_file = file_load($source_file_old_fid);
  file_usage_delete($del_file, 'imagemerge', 'image_style', $form_state['image_style']['isid']);

Looking at the description given in the "Form API Reference" page for the "#managed_file" form field, I read the following sentence:

The #managed_file element is expanded into a set of FAPI elements including two '#submit' buttons one for Upload one for Remove, a '#file' element and a handful of '#hidden' and '#markup' elements to handle progress indication and displaying of already uploaded files.

Looking then at the process function for that form field (file_managed_file_process()), which is the one set from file_element_info(), I notice that it defines a form submission handler for the "Remove" button, and that function (file_managed_file_submit()) calls file_delete().

  if ($button_key == 'remove_button') {
    // If it's a temporary file we can safely remove it immediately, otherwise
    // it's up to the implementing module to clean up files that are in use.
    if ($element['#file'] && $element['#file']->status == 0) {
    // …

I would say there isn't the need for the module using that form field to call file_delete().

  • Ahh so the only thing I need to do is mark the file FILE_STATUS_PERMANENT and call file_save. I guess I should do that if the fid is 0 though, right?
    – darkadept
    Aug 18, 2011 at 21:20
  • Hmm I'm testing this and it seems like the file never get's deleted and it stays in the file_managed table as well. Apparently I do need to delete the file somehow.
    – darkadept
    Aug 18, 2011 at 21:26
  • To notice that the code checks $element['#file']->status; the "Remove" button deletes the file that has been previously uploaded. If you select a file, but you don't upload it, then that button doesn't delete the file.
    – apaderno
    Aug 18, 2011 at 21:39
  • I checked on my test server, and the file is deleted when I click on "Remove," and then on "Save" to save the node. (The file is actually an image that is added to the node.)
    – apaderno
    Aug 18, 2011 at 21:51
  • On my form the file is NOT deleted when I click remove and then submit. See my answer for details.
    – darkadept
    Aug 19, 2011 at 17:01

It's definitely so that you will have to delete the file yourself if the file was made permanent. My guess that could be when the module get's uninstalled? Or if the node get's deleted?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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