3

As described here, I can use Plupload integration module to upload my files to server. They go there, I can see them in temp directory, and that's the point I'm stuck.

Code I'm using for a field is:

'DownloadFile' => array(
  '#title' => t("Download's download"),
  '#title_display' => 'invisible',
  '#type' => 'file',

  '#upload_validators' => array(
    'file_validate_extensions' => array( /* extensions */ ),
    'file_validate_size' => array(variable_get('max_size', 300 * 1024 * 1024)),
  ),
  '#upload_location' => 'public://mymodule/download',
  '#plupload_settings' => array(
    'runtimes' => 'html5',
    'chunk_size' => '10mb',
    'max_file_size' => variable_get('max_size', 300 * 1024 * 1024) . 'b',
  ),
),

In form validation function I get thus in $form_state['values']:

Screenshot

Since the Views for Drupal 7 got reasonably stable, I was using Drupal 7 and managed files. I have literally no idea how should I take this file and plug it into managed table for other functions to use. As you can see from the time difference, it been some time between the moment I was able to upload and now - all this time with no idea. Tried to treat it as '#type' => 'file', but functions for unmanaged don't get it. They require specific name and even if I add '#name' to plupload form element, it still fails.

Is there any way to add file to managed table knowing it's location in temporary://?

  • I found this answer useful when I had a similar problem drupal.stackexchange.com/a/219/5914 – mcaleaa Mar 31 '14 at 15:44
  • Would this work? – Felix Eve Mar 31 '14 at 15:51
  • @mcaleaa not straight answer, but may help a bit, thanks. – Mołot Mar 31 '14 at 19:20
  • @FelixEve this does not answer how to move from temporary:// to public:// - and that's my main concern now. Will need to figure it out. – Mołot Mar 31 '14 at 19:22
  • If you are able to pass a file from form callback to validation callback, then I am sure that in you submit callback you can catch it, move it to any distination as managed or unmanaged file. There are multiple functions that can provide this (you know them better than me): file_save_data, system_retrieve_file and so on.. Rececntly I did something like this without any problem (but i did it without plupload) – xurshid29 Apr 3 '14 at 7:09
4
+300

I didn't really checked all links in this email but I have used Plupload very extensively and worked very well.

<?php 


  $form['upload'] = array(
    '#type' => 'plupload',
    '#title' => '',
    '#description' => t('Maximum file size allowed: 10MB'),
    '#upload_validators' => array(
      'file_validate_extensions' => array('zip rar 7z odt doc docx xls xlsx png jpg pdf rtf txt'),
    ),
    '#plupload_settings' => array(
        'runtimes' => 'html5,flash', // Also consider the order of technologies.
        'chunk_size' => '10mb',
        'unique_names' => TRUE,
        'flash_swf_url' => file_create_url(_plupload_library_path() . '/js/plupload.flash.swf'),
      ),
    );


  return $form;


  // Submit handler:
  //function ..._submit($form, &$form_state) {
  if (!empty($form_state['values']['upload'])) {
    $form_state['uploaded_files'] = quotes_file_save_files($form_state['values']['upload']);
  }

  // }


function quotes_file_save_files($files) {
  $saved_files = array();
  $scheme = 'private://'; // Change to "public://" if you want to move to public files folder.
  foreach ($files as $uploaded_file) {
    if ($uploaded_file['status'] == 'done') {
      $source = $uploaded_file['tmppath'];
      $destination = file_stream_wrapper_uri_normalize($scheme . $uploaded_file['name']);
      $destination = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
      $file = plupload_file_uri_to_object($destination);
      file_save($file);
      // Check the $file object to see if all necessary properties are set. Otherwise, use file_load($file->fid) to populate all of them.
      // $file = file_load($file->fid);
      $saved_files[] = $file;
    }
  }

  return $saved_files;
}


?>

I think the point is, plupload does not save the files to the managed files folder by default, but populates all the data in the $form_state array for you to process and save.

Edit: In relation to the other answer that mentions file object's status should be permanent. I'm sure you already know that the status must be 1. But plupload_file_uri_to_object function sets the $file object's status to 1, so it's not done in the example.

Good luck!

  • Needed to change to $saved_files[] = file_load($file->fid); to get file object properly populated with mime, names, et cetera, so I could pass it for validation. But it seems it'll work. – Mołot Apr 8 '14 at 10:34
  • @Molot file_save() should update the $file object, just like node_save(), right? Unless the extra stuff are added in a hook, $file object should contain everything it just wrote to the database. – AyeshK Apr 8 '14 at 12:19
  • @AyeshK I assumed the same. But no. I did kpr($file) just after file_save($file); in quotes_file_save_files($files) and only fid was filled properly. I don't think re-loading should be needed. Sadly, it was needed. I wasted pretty much time trying to find out why, but ultimately I don't think I care as long as I have a working workaround. – Mołot Apr 8 '14 at 12:38
  • Thanks. I just updated the answer and added a comment about this. – AyeshK Apr 8 '14 at 12:43
  • @Molot did you get this working? I'm trying to save plupload files in a node from a custom form. – 24ma13wg Jun 10 '14 at 21:42
1

I did a multiple gallery plugin that integrated with Ubercart and allowed users to upload multiple images with Plupload, per each attribute option.

Below is the part of the code that I used for uploading files. It goes in the _submit() handler function. The files were saved in the managed files table as permanent files and then were listed in orderable table view.

// Upload files.
foreach ($element['images']['#value'] as $uploaded_file) {
  $source = $uploaded_file['tmppath'];
  $filename = filefield_sources_clean_filename($uploaded_file['name'], array());
  // Move the file to a temporary destination using final base file name.
  $temp_destination = file_stream_wrapper_uri_normalize('temporary://' . $filename);
  $temp_filepath = file_unmanaged_move($source, $temp_destination, FILE_EXISTS_RENAME);
  // Save the files to their final destination.
  if ($file = filefield_sources_save_file($temp_filepath, array(), 'public://your-path/' . $form['nid']['#value'] . '/')) {
    $file->oid = $element['oid']['#value'];
    // Set status to 1, meaning this is a permanent file and should not be
    // cleaned up upon cron run. IMPORTANT!
    $file->status = 1;
    file_save($file);
  }
  else {
    drupal_set_message(t('An error occurred during upload. Please try again.'));
  }
}

Important
You must set $file->status = 1, otherwise the file will be treated as temporary file and will be deleted upon next cron run.

If you need more code/working example, let me know and I'll clean the custom module a bit and post it.

Hope this helps.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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