0

I'm having a problem with the plupload module. The normal upload works perfect, the files are stored in sites\default\files\tmp. I'd like to "walk" through the uploaded files using the hook_submit. It seems, this hook is not called, when pressing start upload on the plupload form. I'm using almost the same hook_submit as the test form in the plupload.module.

What am I doing wrong?

Here is my form definition:

 $form['my_element'] = array(
'#type' => 'plupload',
'#title' => t('Upload files'),
'#description' => t('This multi-upload widget uses Plupload library.'),
'#upload_validators' => array(
  'file_validate_extensions' => array('jpg jpeg gif png txt doc xls pdf ppt pps odt ods odp'),
  'my_custom_file_validator' => array('some validation criteria'),
),
'#plupload_settings' => array(
  'runtimes' => 'flash,html4',
  'url' => url('plupload-handle-uploads', array('query' => array('plupload_token' => drupal_get_token('plupload-handle-uploads')))),
  'max_file_size' => file_upload_max_size() . 'b',
  'chunk_size' => '1mb',
  'unique_names' => TRUE,
  'flash_swf_url' => file_create_url('sites/all/libraries/plupload/js/plupload.flash.swf'),
  'silverlight_xap_url' => file_create_url('sites/all/libraries/plupload/js/plupload.silverlight.xap')
),
);

Here is the submit function:

function get_upload_form_submit($form_id, &$form_state) {
//handle file uploading
global $user;

$saved_files = array(); //Array to capture file objects
$scheme = variable_get('file_default_scheme', 'public') . '://';
$directoryname = 'imagebank'; // Directory where images are collected
$imagebankpath = $scheme . $directoryname;
dpm($imagebankpath);
file_prepare_directory($imagebankpath, FILE_CREATE_DIRECTORY); // Create the folder if   it doesn't exist
// We can't use file_save_upload() because of
// http://www.jacobsingh.name/content/tight-coupling-no-not
// file_uri_to_object();
foreach ($form_state['values']['uploadfiles'] as $uploaded_file) {
if ($uploaded_file['status'] == 'done') {
  $source = $uploaded_file['tmppath'];
  $destination = file_stream_wrapper_uri_normalize($imagebankpath .'/'. $uploaded_file['name']);
  // Rename it to its original name, and put it in its final home.
  // Note - not using file_move here because if we call file_get_mime
  // (in file_uri_to_object) while it has a .tmp extension, it horks.
  $destination = file_unmanaged_move($source, $destination, FILE_EXISTS_RENAME);
  $file = plupload_file_uri_to_object($destination);
  file_save($file);
  $saved_files[] = $file;
}
else {
  form_set_error('uploadfiles', "Upload of {$uploaded_file['name']} failed");
}
}
}

Did I forgot anything? Thx.

1

The submit handler is not executed when clicking on the start upload of the Plupload widget form, this only executes the ajax upload of the files (and the file validators).

To have a submit callback, and handle the logic of the uploaded files (i.e.: move files to a certain directory), you should add a button to the form.

$form['submit'] = array(
    '#type' => 'submit',
    '#value' => t('Submit'),
    '#submit' => array('get_upload_form_submit'),
);

The uploaded files are stored in the form_state under $form_state['values']['my_element'] (the name of your Plupload form field)

Update #1

Some sample code to trigger the form submit callback once the upload of the files is finished by the Plupload uploader. Basically what you need:

  1. A submit button attached to the form to have a submit callback (which handles the uploaded files)
  2. A custom javascript which intercepts the UploadComplete event triggered by the Plupload component
  3. On the UploadComplete interception, trigger a click on the submit button
function YOURMODULE_form($form, &$form_state)
{
    // your form elements with plupload form element

    // add a submit button
    $form['submit'] = array(
        '#type' => 'submit',
        '#value' => t('Save file(s)'),
        '#submit' => array('YOURMODULE_form_submit'),
        '#attributes' => array(
            'class' => array('file-upload-submit'),
        ),
    );

    // attach the custom js to the form
    $form['#attached'] = array(
        'js' => array(
            drupal_get_path('module', 'YOURMODULE') . '/js/YOURMODULE.js',
        ),
    );

    return $form
}

function YOURMODULE_form_submit($form, &$form_state)
{
    // put uploaded files in a 'uploads' directory
    $directory = sprintf('%s://%s',
        variable_get('file_default_scheme', 'public'), 'uploads');

    // be sure directory exists (and create it)
    file_prepare_directory($directory, FILE_CREATE_DIRECTORY);

    // loop through each uploaded file
    $saved_files = array();
    foreach ($form_state['values']['files'] as $file) {
        if ($file['status'] !== 'done') {
            //handle error on upload fail
            continue;
        }

        // move files from tmp directory to defined directory
        $destination = file_unmanaged_move(
            $file['tmppath'], 
            file_stream_wrapper_uri_normalize($directory . '/' . $file['name']), 
            FILE_EXISTS_RENAME
        );

        $saved_file = plupload_file_uri_to_object($destination);
        file_save($saved_file);

        $saved_files[] = $saved_file;
    }

    // keep saved files in form state to be able to stuff afterwards (if needed)
    $form_state['saved_files'] = $saved_files;

    drupal_set_message(t('Files have been uploaded and saved.'));
}

The javascript (under js/YOURMODULE.js)

(function ($) {
    Drupal.behaviors.YOURMODULE = {
        context: null,
        attach: function (context) {
            var that = this,
                uploader = $('.plupload-element', context).pluploadQueue();

            this.context = context;

            if (!uploader) {
                return false;
            }

            uploader.bind('FilesAdded', function() {
                // start upload automatically once files have been added to queue
                that.start();
            });

            uploader.bind('UploadComplete', function() {
                // trigger click on submit button to submit form once upload completed
                that.complete();
            });

            return this;
        },
        start: function() {
            $('.file-upload-submit', this.context)
                .attr('disabled', 'disabled');
        },
        complete: function() {
            $('.file-upload-submit', this.context)
                .removeAttr('disabled')
                .click();
        }
    };

})(jQuery);
7
  • Hi. Thx for your answer. So that means, there is no need for plupload at all, because I could use a standard multiple file uploader. My intention was to have a ajax uploader, so that the user can see the progress. But there must be some code lines to execute the ajax upload after pressing the plupload - button. Do you have an idea, where this logic is, propably inside the plupload module? What do I have to change? – schulle877 Nov 11 '13 at 6:40
  • Well the Plupload provides a visual batch ajax upload with progress. What I've done on one of my projects, is to trigger a form submit when the upload of all files has finished. This way, the webmaster doesn't need to manually press submit and your submit handler is automatically called where your file move logic is executed. Do you need some sample code? – Mike Vranckx Nov 11 '13 at 10:41
  • Well, that sounds great. So, you let plupload's Ajax routine do the basic work and then grab the files from the plupload default upload dir. The only thing I don't know is how to trigger the "upload finished" event. Do you use the drupal module, or do you use a plupload library? A sample code would be great. Thx. – schulle877 Nov 12 '13 at 7:06
  • Yes, exactly :). I added some sample code to help you further (and on how I integrated it on a project). – Mike Vranckx Nov 13 '13 at 13:13
  • Thank you very much for your help. I will test it and come back when I have (hopefully) good news :-) – schulle877 Nov 14 '13 at 11:10

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.