Drupal And the Disappearing Images Mystery
After working many years with a specific framework, you sometimes face difficulties that in other situations, specifically while learning a new language or framework would not even challenge you.One example for such a case is one I’ve encountered this past week, and to tackle it, all I’ve needed to do is to actually read the Drupal docs and not just flip through it.One of my clients came to me and told me that all of the images he’s uploading to his site are deleted from the files directory of his Drupal project after several hours.After checking that the images are created successfully in the Drupal’s temp directory and are then moved to the files directory as they should, I begun checking for any file/image related modules and any Drupal configurations that could hint a relation to the problem.Checking those off I’ve started to look at custom code developed by our programmers, as this is a more time-consuming task I’ve not started with it but knew from the beginning that this is probably where the culprit could be found.While carefully combing the code I’ve landed upon a form api piece of code related to an image field similar to this:
<!--?php
// Use the #managed_file FAPI element to upload an image file.
$form['image_example_image_fid'] = array(
'#title' => t('Image'),
'#type' => 'managed_file',
'#description' => t('The uploaded image will be displayed on this page using the image style chosen below.'),
'#default_value' => variable_get('image_example_image_fid', ''),
'#upload_location' => 'public://image_example_images/',
);
?>
This piece of code will add a nice file/image field to the page and will allow you to attach an image to the current entity.After finding the “managed_file” type documentation the problem and the solution was clear.
Note: New files are uploaded with a status of 0 and are treated as temporary files which are removed after 6 hours via cron. Your module is responsible for changing the $file objects status to FILE_STATUS_PERMANENT and saving the new status to the database. Something like the following within your submit handler should do the trick.
<!--?php
// Load the file via file.fid.
$file = file_load($form_state['values']['my_file_field']);
// Change status to permanent.
$file->status = FILE_STATUS_PERMANENT;
// Save.
file_save($file);
// Record that the module (in this example, user module) is using the file.
file_usage_add($file, 'user', 'user', $account->uid);
?>
So in order to prevent the (weird – in my opinion) automatic 6 hour cron deletion of the uploaded images you have to add a submit handler and inside it add that piece of code.To clarify and help those in need, this is an expanded example of a form and submit functions.
<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form</span> = <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;"><a class="local" href="https://api.drupal.org/api/drupal/includes%21form.inc/function/drupal_get_form/7" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="Returns a renderable form array for a given form ID.">drupal_get_form</a></span>(<span class="php-string" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'my_module_example_form'</span>);...<span class="php-keyword" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">function</span> <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">my_module_example_form</span>(<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form</span>, &<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form_state</span>) { $form['image_example_image_fid'] = <a class="php-manual" href="http://php.net/array" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="array array([mixed $... = '']) Create an array">array</a>( '#title' => t('Image'), '#type' => 'managed_file', '#description' => t('The uploaded image will be displayed on this page using the image style chosen below.'), '#default_value' => variable_get('image_example_image_fid', ''), '#upload_location' => 'public://image_example_images/', );<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;"> $form</span>[<span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'<a class="local" href="https://api.drupal.org/api/drupal/includes%21form.inc/function/theme_submit/7" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="Returns HTML for a submit button form element.">submit</a>'</span>] = <span class="php-keyword" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">array</span>( <span class="php-string" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'#type'</span> => <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'<a class="local" href="https://api.drupal.org/api/drupal/includes%21form.inc/function/theme_submit/7" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="Returns HTML for a submit button form element.">submit</a>'</span>, <span class="php-string" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'#value'</span> => <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;"><a class="local" href="https://api.drupal.org/api/drupal/includes%21bootstrap.inc/function/t/7" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="Translates a string to the current language or to a given language.">t</a></span>(<span class="php-string" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">'Submit'</span>), ); <span class="php-keyword" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">return</span> <span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form</span>;}<span class="php-keyword" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">function</span> <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">my_module_example_form_validate</span>(<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form</span>, &<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form_state</span>) { <span class="php-comment" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">// Validation logic.</span>}<span class="php-keyword" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">function</span> <span class="php-function-or-constant" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">my_module_example_form_submit</span>(<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form</span>, &<span class="php-variable" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">$form_state</span>) { <span class="php-comment" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: inherit; font-stretch: inherit; line-height: inherit;">// Submission logic. // Load the file via file.fid. $file = file_load($form_state['values']['my_file_field']); // Change status to permanent. $file->status = <a class="local" href="https://api.drupal.org/api/drupal/includes%21file.inc/constant/FILE_STATUS_PERMANENT/7" style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-stretch: inherit; line-height: inherit; color: rgb(0, 102, 204);" title="Indicates that the file is permanent and should not be deleted.">FILE_STATUS_PERMANENT</a>; // Save. file_save($file); // Record that the module (in this example, user module) is using the file. file_usage_add($file, 'user', 'user', $account->uid); <span style="font-family: inherit; font-size: inherit; font-style: inherit; font-variant: inherit; font-weight: 700; font-stretch: inherit; line-height: inherit;"> // a more generic example of file_usage_add // file_usage_add($file, 'my_module_name', 'user or node or any entity', 'that entity id'); // you don't need to use "file_usage_add" if you're not attaching the image to an entity</span></span>}
Originally posted on <a href="https://ehudshahak.wordpress.com/2014/11/29/drupal-and-the-disappearing-images-mystery/">my personal blog</a>.