9

I have the following code in my form.

$form['new']['upload'] = array(
  '#type' => 'file',
  '#title' => t(''),
  '#size' => 40,
);

On the submission handler, it returns the file name but it does not save the file and return a file object. What else do I need to do?

What I am trying to do is create a block where you can upload a file that it is saved in a node's file field.

8

Take a look at file_save_upload() and the functions which call it.

The function will handle the validation of the file, and save it to a new location. In Drupal 7 this also adds the file to file_managed table.
Note that the file will be stored as a temporary file, so make sure to set the status of the file to permanent afterwards.

You will probably want to implement the file_save_upload function inside your form's validation hook (before the submit handler), so you can alert the user if the file upload failed, or did not meet your validation requirements.

If the name of the image field you are trying to validate is image, then the first parameter of file_save_upload should be image, as such:

$path = file_save_upload('image', ...);

This function will then return the path on the server to which the image was uploaded (so you can for example store that path in a custom database field).

4

You are missing this in your form definition:

   $form['#attributes']['enctype'] = 'multipart/form-data'; // If this is not here, upload will fail on submit

Here's the logic I use to create a file upload widget on a form:

   // these give us the file upload widget: 
   $form['#attributes']['enctype'] = 'multipart/form-data'; // If this is not here, upload will fail on submit
   $form['fid'] = array( '#title'        => t('Upload image'),
                         '#type'         => 'file',
                         '#description'  => t('Images must be one of jpg, bmp, gif or png formats.'),
                       ); 

And here's the counterpart to that logic, which I have in my form's validate callback, because I have image filename restrictions in my logic, but you can place this in the submit callback if you want:

   // @see: http://api.drupal.org/api/function/file_save_upload/6
   // $file will become 0 if the upload doesn't exist, or an object describing the uploaded file
   $file = file_save_upload( 'fid' );
   error_log( 'file is "'.print_r( $file, true ).'"' );
   if (!$file) {
      form_set_error('fid', t('Unable to access file or file is missing.'));
   }

that's it.

  • 3
    You actually don't need $form['#attributes']['enctype'] in Drupal 7. It's taken care of automatically – user724228 Sep 15 '11 at 23:41
  • 3
    you don't need the multipart/form-data for drupal 7, It is build in drupal 7 when using a file field. – FLY Sep 4 '12 at 13:34
  • @bsenftner I'm using the same method as you are, but when I try it out, I find that $file === null, which means that no file was uploaded (according to the specs: api.drupal.org/api/drupal/includes!file.inc/function/…) What should I do in that case? How can I debug this kind of thing? – Shawn Oct 10 '12 at 19:26
  • @Shawn: are you working in Drupal 7? This logic is tested for Drupal 6. I've not had a chance to try it on D7 yet, so, if you're in D7 then "I don't know". If you're in D6, then it should be working - are you sure 'fid' is the field name of your file upload widget? – Blake Senftner Oct 10 '12 at 23:21
  • Yes to both questions: I'm sure I've got the right name for the widget and I'm using D7. I think I should make this a new question... – Shawn Oct 11 '12 at 13:33
3

I have a generic validation function I use primarily in themes that need to support upload of images. You might be able to use it as it, or with minor changes, but this should get you far.

/**
 * Validate/submit handler used for handling image uploads
 */
function module_upload_image_validate($form, &$form_state) {
  // This is not needed, I use this to use the same validate function
  // for several fields.
  $key = $form['#key'];
  $file = file_save_upload($key, array(
    'file_validate_is_image' => array(),
    'file_validate_extensions' => array('png gif jpg jpeg'),
  ));
  if ($file) {
    // Get the image info to get the correct extension for the uploaded file.
    $info = image_get_info($file->filepath);
    if (file_move($file, 'destination/filename'. $info['extension'], FILE_EXISTS_REPLACE)) {
      // Mark the file for permanent storage.
      file_set_status($file, FILE_STATUS_PERMANENT);
      // Update the files table.
      drupal_write_record('files', $file, 'fid');
      $form_state['values'][$key] = $file->filepath;
    }
    else {
      form_set_error($key, t('Failed to write the uploaded file to the site’s files folder.'));
    }
  }
}

Using this function, you will get the filepath as the the value in form submit handler. You might want the file id instead, depending on your usage.

protected by Community May 9 '13 at 10:11

Thank you for your interest in this question. Because it has attracted low-quality or spam answers that had to be removed, posting an answer now requires 10 reputation on this site (the association bonus does not count).

Would you like to answer one of these unanswered questions instead?

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