Jump to content

upload progressbar for wire upload?


Marcel Epp
 Share

Recommended Posts

Hi,

i have build a form with somas excellent example. I have a field for email and one field for file upload.

The files get uploaded to pages.

How can i get a file progressbar to work?

Or put something like dropzone in it? Has anyone an idea how to do that? 

Link to comment
Share on other sites

The first thing to understand is, that real progress bars are not possible when using standard html forms without any javascript involvement, as the files are uploaded after a form is submitted, after essentially the current page is "left behind", but before the actual site reload with the response data from the server. That's why you need some javascript/ajax upload to get progress bars. If you're currently not using any ajax logic this might bring some need of refactoring on the server-side as well. And that's also the reason why WireUpload is not really the part to ask for, as it's only responsible of handling already submitted files on the server. How files are send to the server doesn't matter for it.

  • Like 2
Link to comment
Share on other sites

// so we only initiate plupload if a form with id fileUploadForm is present on the page
// you can change it to look for a class name if you prefer..
var filesUpload = document.getElementById("fileUploadForm");
if (typeof fileUploadForm !== 'undefined') {
    // this is the part of the form where people can drag and drop files into
    // if it should be the whole form you can strip the next line and change all dropArea vars to filesUpload
    var dropArea = document.getElementById("dropArea");
    
    // the next 3 events are only to visualize drag and drop
    // they're basically just adding/removing the dragOver class to dropArea
    dropArea.addEventListener('dragover', function(e) {
        this.classList.add("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener('dragleave', function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener("drop", function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);

    // here we actually initiate pluploader
    var uploader = new plupload.Uploader({
        browse_button: dropArea, // this can be an id of a DOM element or the DOM element itself
        drop_element: dropArea,
        url: './',
        resize: {width: 3000, height: 3000},
        headers: {
            "X-Requested-With": "XMLHttpRequest" // without this Processwire's $config->ajax won't work
        },
        filters: {
            mime_types : [
                { title : "Image files", extensions : "jpg,jpeg,gif,png" },
                { title : "Video files", extensions : "mpg,mpeg,mp4,mov,avi,wmv" },
                { title : "Zip files", extensions : "zip" }
            ]
        },
        runtimes: 'html5,flash,silverlight,html4',
        flash_swf_url: 'plupload/Moxie.swf',
        required_features: true
    });

    uploader.init();

    // here you can show a preview of each file (before actual upload)
    uploader.bind('FilesAdded', function(up, files) {
        var html = '';
        plupload.each(files, function(file) {
            /* check file.size, remove if exceeds limit */
            html += '<li id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></li>';
        });
        document.getElementById('fileList').innerHTML += html;
        uploader.start();
    });

    // this one handles the actual progress, I'm currently just showing in percents (without progress bar)
    // but you can use file.percent for whatever you like (e.g. changing the width of an element with it)
    uploader.bind('UploadProgress', function(up, file) {
        if(file.percent == 100 && file.status != plupload.DONE) {
            file.percent = 99;
        }
        document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
    });

    // after a file is ready, my PHP script is responding with the pageimage file, so I'm swapping the preview with the response
    uploader.bind('FileUploaded', function(up, file, result) {
        // remove upload progress for this file
        var progressElement = document.getElementById(file.id);
        progressElement.parentNode.remove(progressElement);

        // prepend uploaded files to gallery
        var gallery = document.getElementById('groupGallery');
        gallery.insertAdjacentHTML('afterbegin', result.response);
    });

    // error handler..
    uploader.bind('Error', function(up, err) {
        // document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
        console.log("Error #" + err.code + ": " + err.message);
    });
}

So this is exactly what I use right now. Added only a few more comments. Hope it helps to get you started.

You can customize plupload for your needs and as far as I remember there is somewhere documentation on how to strip unneded runtimes, like flash or silverlight. But that depends on your needs ;-)

  • Like 3
Link to comment
Share on other sites

you mean in some example script of plupload?

The code I posted above is all I have for plupload.

On the serverside I had a form and the process logic already, so plupload is just another way of sending the files to the php.

Maybe I don't really understand what you mean?

  • Like 1
Link to comment
Share on other sites

When i used plupload as stand alone, there are 3 files. The index.php where pluploader is inside + options for pluploader itself.

The upload.php where i can change the configuration for the upload. And a dump.php that is showed after the file upload.

The upload.php is the file that is in the form action.

I tried to do the same in Processwire. But i think, that didn't work. Did you connect plupload with wireupload?

Link to comment
Share on other sites

ah okay.

Usually I do the php/html first, to ensure (somewhat) working form for js disabled users (but maybe that's not needed for you) I have everything in one template file, you could split markup and logic but in the beginning it's probably easier

my form action is like action='./' so the form submits to the page it's on. and pluploads url is the same ('./') so posting to the current page

I started with examples from soma

https://gist.github.com/somatonic/5233338 easier because normal html form is used (at least I found it easier in the beginning)

https://gist.github.com/somatonic/5236008 using PW form api & inputfields

There are more examples out there, using google is more effective than forum search

Ah, in my /assets/files/ folder I've got .tmp_uploads the period makes it non accessible by the web, this method is mentioned here multiple times to prevent malicious stuff

$upload_path = $config->paths->assets . 'files/.tmp_uploads/';

And than you can do what ever you like with the file, create a new page for it, or add it to an existing pages file/image field or even have your own storing system..

after that you delete the file from your tmp

  • Like 1
Link to comment
Share on other sites

I think the first problem for me is to initate plupload like you described above.

On my site i have for testing only:

<form  id="fileUploadForm" method="post" action="./">  
 
</form> 

after that in my footer and your code:

<script src="<?php echo $config->urls->templates?>scripts/vendor/jquery.min.js"></script>
<script src="<?php echo $config->urls->templates?>scripts/plupload.full.min.js"></script>
<script src="<?php echo $config->urls->templates?>scripts/jquery.plupload.queue.js"></script>

<script type="text/javascript">

  // so we only initiate plupload if a form with id fileUploadForm is present on the page
    // you can change it to look for a class name if you prefer..
    var filesUpload = document.getElementById("fileUploadForm");
    if (typeof fileUploadForm !== 'undefined') {
    // this is the part of the form where people can drag and drop files into
    // if it should be the whole form you can strip the next line and change all dropArea vars to filesUpload
    var dropArea = document.getElementById("dropArea");
    
    // the next 3 events are only to visualize drag and drop
    // they're basically just adding/removing the dragOver class to dropArea
    dropArea.addEventListener('dragover', function(e) {
        this.classList.add("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener('dragleave', function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener("drop", function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);

    // here we actually initiate pluploader
    var uploader = new plupload.Uploader({
        browse_button: dropArea, // this can be an id of a DOM element or the DOM element itself
        drop_element: dropArea,
        url: './',
        resize: {width: 3000, height: 3000},
        headers: {
            "X-Requested-With": "XMLHttpRequest" // without this Processwire's $config->ajax won't work
        },
        filters: {
            mime_types : [
                { title : "Image files", extensions : "jpg,jpeg,gif,png" },
                { title : "Video files", extensions : "mpg,mpeg,mp4,mov,avi,wmv" },
                { title : "Zip files", extensions : "zip" }
            ]
        },
        runtimes: 'html5,flash,silverlight,html4',
        flash_swf_url: 'plupload/Moxie.swf',
        required_features: true
    });

    uploader.init();

    // here you can show a preview of each file (before actual upload)
    uploader.bind('FilesAdded', function(up, files) {
        var html = '';
        plupload.each(files, function(file) {
            /* check file.size, remove if exceeds limit */
            html += '<li id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></li>';
        });
        document.getElementById('fileList').innerHTML += html;
        uploader.start();
    });

    // this one handles the actual progress, I'm currently just showing in percents (without progress bar)
    // but you can use file.percent for whatever you like (e.g. changing the width of an element with it)
    uploader.bind('UploadProgress', function(up, file) {
        if(file.percent == 100 && file.status != plupload.DONE) {
            file.percent = 99;
        }
        document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
    });

    // after a file is ready, my PHP script is responding with the pageimage file, so I'm swapping the preview with the response
    uploader.bind('FileUploaded', function(up, file, result) {
        // remove upload progress for this file
        var progressElement = document.getElementById(file.id);
        progressElement.parentNode.remove(progressElement);

        // prepend uploaded files to gallery
        var gallery = document.getElementById('groupGallery');
        gallery.insertAdjacentHTML('afterbegin', result.response);
    });

    // error handler..
    uploader.bind('Error', function(up, err) {
        // document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
        console.log("Error #" + err.code + ": " + err.message);
    });
}


 
</script> 

Did i now should see some plupload window? My site is empty. As far i understand you initiate plupload with a the id FileUploadForm.

Link to comment
Share on other sites

Ah, what I meant by "On the serverside I had a form and the process logic already" is that I have a fully functional form like

<form action="./" method="post">
	<div id="dropArea">
		<input class="dragDropFileUploadField" type="file" name="file[]" accept="jpg,jpeg,png,gif,mpg,mpeg,mp4,avi,wmv,mov,zip" multiple>
		<button type="submit" name="action" value="submit">Upload</button>
	</div>
</form> 

In the JS

var uploader = new plupload.Uploader({
        browse_button: dropArea, // this can be an id of a DOM element or the DOM element itself
        drop_element: dropArea,

you're defining a click and a drag&drop area in this case called "dropArea" so this element needs to be present in your form.

Have you read plupload's docs? http://www.plupload.com/docs/Getting-Started

EDIT: plupload is a little like Processwire as it doesn't provide the UI, instead it gives you the API and events and let's you define your upload area.

Edited by Can
  • Like 1
Link to comment
Share on other sites

Maybe you can share your code so far?

It's actually auto uploading, when you use the js as I posted. So every file will be automatically uploaded after adding..

You could look into browser delevopment tools Network tab. When you got the page with your form finished loading and then open the network tab it should be empty.

Once you drag or choose a file, a new entry of type xhr should appear in network tab

Is your php already doing anything with uploaded files? or at least supposed to do already, or how does your php part look right now?

  • Like 1
Link to comment
Share on other sites

Here is my code. Hope it is not to messy....

This is the site where the form is on:

<!-- include head start -->
<?php include('./_head_jquery_upload.php'); ?>
<!-- include head end -->

<!-- include header start -->
<?php include('./_header.php'); ?>
<!-- include header end -->

<div id="basic-site-text" class="row content-box">
  <div class="large-12 columns"></div>
  <div class="medium-9 columns content-box-column-left">

<?php

/**
 * ### Example front-end form template with file upload and fields ###
 *
 * - with files (images) upload to page field
 * - adds new page on the fly and adds uploaded images
 * - prevents CRSF attacks, this also prevents double post by refresh page after submit
 * - has required fields with error messages inline
 * - sanitizing and saving values to a page
 * - jquery example with disabled submit button on form submit
 *
 * Edit add or remove form markup below and configure this section according to what you need.
 *
 */
        
// ------------------------------ FORM Processing ---------------------------------------

include("./form-process-sw.php");

?>

<!-- ========================= FORM HTML markup  ================================== -->

<?php

/**
 * Some vars used on the form markup for error and population of fields
 *
 * $errors[fieldname]; to get errors
 * $form_fields[fieldname]['value'];
 *
 * Some helper function to get error markup
 * echo showError(string);
 *
 * Prevent CSRF attacks by adding hidden field with name and value
 * you an get by using $session->CSRF
 * $session->CSRF->getTokenName();
 * $session->CSRF->getTokenValue();
 *
 * $errors['csrf']; used to check for CSRF error
 *
 */

?>

<?php if(!$success) : ?>

    <?php if(!empty($errors)) echo showError("Die Form enthält Fehler!"); ?>
    <?php if(!empty($errors['csrf'])) echo showError($errors['csrf']); ?>

    <form name="myform" class="myform" id="fileUploadForm" method="post" action="./" enctype="multipart/form-data">

        <input type="hidden" name="<?php echo $session->CSRF->getTokenName(); ?>" value="<?php echo $session->CSRF->getTokenValue(); ?>"/>

        <label>Bitte Service auswählen:
          <select name="select_service" id="select-service-dropdown" onChange="window.location.href=this.value">
            <option selected="selected" value="/service/bilder-in-sw/">Farbbilder in Schwarzweiß umwandeln</option>
            <option value="/service/bildoptimierung/">Bilder optimieren</option>
            <option value="/service/portrait-optimierung/">Portraitbilder optimieren</option>
            <option value="/service/pdf-zu-jpg-umwandeln/">PDF-Dateien zu JPG-Dateien umwandeln</option>
            <option value="/service/datencheck/">PDF-Prüfbericht anfordern</option>
          </select>
        </label>

        <div class=" <?php if(isset($errors['email'])) echo "error";?>">
            <label for="email">Ihre E-Mail Adresse: * </label>
            <input type="text" name="email" id="email" placeholder='max.mustermann@email.de' value="<?php 
            // zeigt die E-Mail Adresse des Users wenn eingeloggt.
            if($user->isLoggedin()) {
              if (empty($_POST["email"]))
                echo $user->email;
            }
            
            echo $sanitizer->entities($form_fields['email']['value']); ?>"/>
            <?php if(isset($errors['email'])) echo showError($errors['email']); ?>
        </div>

        <?php
      // if user is logged in... show some content specifically for logged-in users
              if ($user->isLoggedin()) {
               echo "<div class='callout secondary'>";
               echo $page->service_email_info_logged_in;
               echo "</div>";
              }
              else {
               echo "<div class='callout secondary'>";
               echo $page->service_email_info_logged_out;
               echo "</div>";
              }    
     ?>

        <div id="dropArea" class=" <?php if(isset($errors['file'])) echo "error";?>">
          <label for="file">Ihre Bilddateien: * </label>
          <input class="dragDropFileUploadField" type="file" name="file[]" accept="image/jpg,image/jpeg,image/gif,image/png" multiple />
          <!--<button type="submit" name="action" value="submit">Upload</button>-->
          <?php
            // show upload errors
            if(isset($errors['file'])){
                // if multiple errors
                if(is_array($errors['file'])){
                    foreach($errors['file'] as $e){
                        echo showError($e);
                    }
                } else { // if single error
                    echo showError($errors['file']);
                }
            }
            ?>
        </div>


        <!--<div class=" <?php if(isset($errors['images'])) echo "error";?>">
            <label for="images">Ihre Bilddateien: * </label>
            <input type="file" name="images[]" id="file_upload" multiple="multiple" size="40" accept="image/jpg,image/jpeg,image/gif,image/png"/>
        </div>-->


        <div>
            <div id="fileList"></div><br><br>
            <input type="hidden" name="action" id="action" value="send"/>
            <input data-toggle="loadingModal" type="submit" name="submit" id="submit" value="Absenden" class="button service_button"/>
        </div>
        <br />
        <!-- Fehlermeldung plupload -->
        <pre id="console"></pre>

</form>
      <div class="full reveal" id="loadingModal" data-reveal>
        <div>
          <img src="<?php echo $config->urls->templates?>images/loading_circle.gif" alt="Intropsective Cage"><br>
        </div>
      </div>

<?php else: ?>

    <p><?php echo $success_message; ?></p>
    <!--<p><?php var_dump($files) ?></p>
    <p><?php var_dump($form_fields ["email"]["value"]) ?></p>
    <p><?php echo ($form_fields ["email"]["value"]); ?></p>
    <p><?php var_dump($withoutExt)?></p>-->
    

<?php endif; ?> 

    </div><!-- Ende Container -->

  <div class="medium-3 columns content-box-column-right">
  	<!--<div id="info_text"><?php echo $page->service_info_headline; ?></div>
  	<div id="info_general"><?php echo $page->service_info_text_general; ?></div>-->
    <div id="info_sw_image"><?php foreach($page->service_info_image_sw as $image) {
    echo "<img src='$image->url'>";
    } ?></div>
  	<div id="info_sw"><?php echo $page->service_info_text_sw; ?></div>
  </div>
</div>

<!-- include footer start -->
<?php include('./_foot.php'); ?>
<!-- include footer end -->

<!-- include footer start -->
<?php include('./_foot_service_sw.php'); ?>
<!-- include footer end -->

This is the form_process that handles the upload and creates a xml from every file and stores them into pages.

<?php
// ------------------------------ FORM Configuration ---------------------------------------

// --- Some default variables ---
$success_message   = "<div id='form-success-message' class='text-center'><i class='fi-check'></i><br><h4>Danke, Ihre Daten wurden übermittelt.</h4></div>";

// --- All form fields as nested array ---
// using html form field name => template field nam, from the page you're going to create
$form_fields = array(
    'email'               => array('type' => 'email', 'value' => '', 'required' => true),
    'file'                => array('type' => 'file', 'required' => true)
);

// --- WireUpload settings ---
$upload_path        = $config->paths->assets . "files/service_upload_files/service1/"; // tmp upload folder
$file_extensions    = array('jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff');
$max_files          = 3;
$max_upload_size    = 1*14336*14336; // make sure PHP's upload and post max size is also set to a reasonable size 1*102400 = 100 MB
$overwrite          = false;

// --- Page creation settings ---
$template           = "service-upload-files"; // the template used to create the page
$parent             = $pages->get("/service/bilder-in-sw/");
$file_field         = "images";
$page_fields        = array('email');

// $page_fields = define the fields (except file) you want to save value to a page
// this is for the form process to populate page fields.
// Your page template must have the same field names existent



// ------------------------------ FORM Processing ---------------------------------------

$errors            = null;
$success           = false;

// helper function to format form errors
function showError($e){
    return "<div class='alert callout'><p class='error'>$e</p></div>";
}

// dump some variables
// var_dump($_FILES,$_POST,$_SESSION);

/**
 * Cast and save field values in array $form_fields
 * this is also done even form not submited to make populating the form later easier.
 *
 * Also used for pupulating page when form was valid
 */
$required_fields = array();
foreach($form_fields as $key => $f){
    if($f['type'] == 'email'){
        $form_fields[$key]['value'] = $sanitizer->email($input->post->$key);
    }
    // store required fields in array
    if($f['required']) $required_fields[] = $key;
}

/**
 * form was submitted, start processing the form
 */

if($input->post->action == 'send'){

    // validate CSRF token first to check if it's a valid request
    if(!$session->CSRF->hasValidToken()){
        $errors['csrf'] = "Die Formulardaten wurden nicht richtig ausgefüllt. Bitte versuchen Sie es erneut.";
    }

    /**
     * Ceck for required fields and make sure they have a value
     */
    foreach($required_fields as $req){

        // required upload file field
        if($form_fields[$req]['type'] == 'file'){
            if(empty($_FILES[$req]['name'][0])){
                $errors[$req] = "Bitte wählen Sie mindestens 1 Datei für den Upload aus.";
            }
        // reqired text fields
        } else if($form_fields[$req]['type'] == 'email'){
            if(!strlen($form_fields[$req]['value'])){
                $errors[$req] = "Dieses Feld muss ausgefüllt sein.";
            }
            // reqired email fields
            if($form_fields[$req]['type'] == 'email'){
                if($form_fields[$req]['value'] != $input->post->$req){
                    $errors[$req] = "Bitte geben Sie Ihre E-Mail Adresse an.";
                }
            }
        }
    }

    /**
     * if no required errors found yet continue file upload form processing
     */
    if(empty($errors)) {

        // RC: create temp path if it isn't there already
        if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

        // setup new wire upload
        $u = new WireUpload($file_field);
        $u->setMaxFiles($max_files);
        $u->setMaxFileSize($max_upload_size);
        $u->setOverwrite($overwrite);
        $u->setDestinationPath($upload_path);
        $u->setValidExtensions($file_extensions);

        // start the upload of the files
        $files = $u->execute();

        // if no errors when uploading files
        if(!$u->getErrors()){

            // create the new page to add field values and uploaded images
            $uploadpage = new Page();
            $uploadpage->template = $template;
            $uploadpage->parent = $parent;

            // add title/name and make it unique with time and uniqid
            $uploadpage->title = date("d-m-Y H:i:s") . " - " . uniqid();

            // populate page fields with values using $page_fields array
            foreach($page_fields as $pf){
                if($templates->get($template)->hasField($pf)){
                    $uploadpage->$pf = $form_fields[$pf]['value'];
                } else {
                    throw new WireException("Template '$template' has no field: $pf");
                }
            }

            // RC: for safety, only add user uploaded files to an unpublished page, for later approval
            // RC: also ensure that using v2.3+, and $config->pagefileSecure=true; in your /site/config.php
            $uploadpage->addStatus(Page::statusUnpublished);
            $uploadpage->save();

            // Now page is created we can add images upload to the page file field
            foreach($files as $filename) {
                $uploadpage->$file_field = $upload_path . $filename;
                // remove tmp file uploaded
                //unlink($upload_path . $filename);
            }
            $uploadpage->save();

            // create XML files for switch

            // remove extension from files
            $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $files);
            
            foreach($withoutExt as $withoutExt_string) { 

            $doc = new DOMDocument('1.0');
            // we want a nice output
            $doc->formatOutput = true;

            $root = $doc->createElement('phpemail');
            $root = $doc->appendChild($root);

            $email = $doc->createElement('email');
            $email = $root->appendChild($email);

            $text = $doc->createTextNode(($form_fields ["email"]["value"]));
            $text = $email->appendChild($text);

            $doc->save($upload_path . $withoutExt_string . ".xml");
            
            }

            // $success_message .= "<p>Page created: <a href='$uploadpage->url'>$uploadpage->title</a></p>";
            $success = true;

            // reset the token so no double posts happen
            // also prevent submit button to from double clicking is a good pratice
            $session->CSRF->resetToken();

        } else {
            // errors found
            $success = false;

            // remove files uploaded
            foreach($files as $filename) unlink($upload_path . $filename);

            // get the errors
            if(count($u->getErrors()) > 1){ // if multiple error
                foreach($u->getErrors() as $e) {
                    $errors[$file_field][] = $e;
                }
            } else { // if single error
                $errors[$file_field] = $u->getErrors();
            }
        }
    }
}

And this is the footer where i put your plupload code:

<!-- jQuery first, then foundation JS. -->
    <script src="<?php echo $config->urls->templates?>scripts/vendor/jquery.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/vendor/what-input.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/foundation.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/app.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/onchange_dropdown_service.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/email_service_validation.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/plupload.full.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/jquery.plupload.queue.js"></script>
    <script src="<?php echo $config->urls->templates?>langs/de.js"></script>
    <script type="text/javascript">

  // so we only initiate plupload if a form with id fileUploadForm is present on the page
    // you can change it to look for a class name if you prefer..
    var filesUpload = document.getElementById("fileUploadForm");
    if (typeof fileUploadForm !== 'undefined') {
    // this is the part of the form where people can drag and drop files into
    // if it should be the whole form you can strip the next line and change all dropArea vars to filesUpload
    var dropArea = document.getElementById("dropArea");
    
    // the next 3 events are only to visualize drag and drop
    // they're basically just adding/removing the dragOver class to dropArea
    dropArea.addEventListener('dragover', function(e) {
        this.classList.add("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener('dragleave', function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);
    dropArea.addEventListener("drop", function(e) {
        this.classList.remove("dragOver");
        e.preventDefault();
        e.stopPropagation();
    }, false);

    // here we actually initiate pluploader
    var uploader = new plupload.Uploader({
        browse_button: dropArea, // this can be an id of a DOM element or the DOM element itself
        drop_element: dropArea,
        url: './',
        resize: {width: 3000, height: 3000},
        headers: {
            "X-Requested-With": "XMLHttpRequest" // without this Processwire's $config->ajax won't work
        },
        filters: {
            mime_types : [
                { title : "Image files", extensions : "jpg,jpeg,gif,png" },
                { title : "Video files", extensions : "mpg,mpeg,mp4,mov,avi,wmv" },
                { title : "Zip files", extensions : "zip" }
            ]
        },
        runtimes: 'html5,flash,silverlight,html4',
        flash_swf_url: 'plupload/Moxie.swf',
        required_features: true
    });

    uploader.init();

    // here you can show a preview of each file (before actual upload)
    uploader.bind('FilesAdded', function(up, files) {
        var html = '';
        plupload.each(files, function(file) {
            /* check file.size, remove if exceeds limit */
            html += '<li id="' + file.id + '">' + file.name + ' (' + plupload.formatSize(file.size) + ') <b></b></li>';
        });
        document.getElementById('fileList').innerHTML += html;
        uploader.start();
    });

    /* this one handles the actual progress, I'm currently just showing in percents (without progress bar)
    // but you can use file.percent for whatever you like (e.g. changing the width of an element with it)
    uploader.bind('UploadProgress', function(up, file) {
        if(file.percent == 100 && file.status != plupload.DONE) {
            file.percent = 100;
        }
        document.getElementById(file.id).getElementsByTagName('b')[0].innerHTML = '<span>' + file.percent + "%</span>";
    });

    /* after a file is ready, my PHP script is responding with the pageimage file, so I'm swapping the preview with the response
    uploader.bind('FileUploaded', function(up, file, result) {
        // remove upload progress for this file
        var progressElement = document.getElementById(file.id);
        progressElement.parentNode.remove(progressElement);

        // prepend uploaded files to gallery
        var gallery = document.getElementById('groupGallery');
        gallery.insertAdjacentHTML('afterbegin', result.response);
    });*/

    // error handler..
    uploader.bind('Error', function(up, err) {
        // document.getElementById('console').innerHTML += "\nError #" + err.code + ": " + err.message;
        console.log("Error #" + err.code + ": " + err.message);
    });
}

</script>
  </body>
</html>
Link to comment
Share on other sites

Try to change your file field from

<input class="dragDropFileUploadField" type="file" name="file[]" accept="image/jpg,image/jpeg,image/gif,image/png" multiple />

to

<input class="dragDropFileUploadField" type="file" name="images[]" accept="image/jpg,image/jpeg,image/gif,image/png" multiple />

because your defined your $file_field = "images"

  • Like 1
Link to comment
Share on other sites

I changed the name to images. After that i disabled plupload to see if my upload still works.

I took away the id dropArea and on the input filed dragDropFileUploadField. Then without plupload the upload is fine.

<label for="file">Ihre Bilddateien: * </label>

        <div id="dropArea" class=" <?php if(isset($errors['images'])) echo "error";?>">
          
          <input class="dragDropFileUploadField" type="file" name="images[]" accept="image/jpg,image/jpeg,image/gif,image/png" multiple="multiple" />
          <!--<button type="submit" name="action" value="submit">Upload</button>-->
          <?php
            // show upload errors
            if(isset($errors['images'])){
                // if multiple errors
                if(is_array($errors['images'])){
                    foreach($errors['images'] as $e){
                        echo showError($e);
                    }
                } else { // if single error
                    echo showError($errors['images']);
                }
            }
            ?>
        </div>

Without plupload the input field looks like this:

post-3507-0-79013800-1456921504_thumb.pn

With plupload the file list looks like this:

post-3507-0-22879400-1456921539_thumb.pn

here on the second picture with plupload the input type says that no files are selected.

I think the input type get no files. I enabled/disabled the auto upload function to see if there is a difference.

The ideal way for me would be that i press submit button the uploader starts the upload and the form gets submitted.

Link to comment
Share on other sites

The ideal way for me would be that i press submit button the uploader starts the upload and the form gets submitted.

That's exactly what I tried to tell you above. As long as you're not using javascript to submit the form without page reload you simply cannot have upload bars. Submitting a form does trigger by default trigger a page-reload, which is not observable by anything javascript.

If you're not handling the full form submittion via ajax, you've to separate the steps of submitting the form and uploading files. You could potentially manage to have the files uploaded via ajax on hitting submit, but before the form is sent, but there's no page to upload files to before the form itself is sent.

  • Like 1
Link to comment
Share on other sites

Thank your for your answer.

As far as i understand one solution would be to have a site with the email field and a submit button (next button).

After i hit that, it must create a site and keep the email adress stored and sends me to another site.

On the next site i can upload my files and attech them to the created site + generate my xml files from the filename with the stored email adress.

Would that be a solution?

I think using javascript to submit the form is to difficult for me.

Link to comment
Share on other sites

The question is, if progress bars are really worth the hassle of a multi step form. Also you could always put files in a temporary folder via plupload and submit the form just with the filenames / path via a traditional submit, where you don't upload the files, but just add them to the page by the submitted path / filename info.

  • Like 1
Link to comment
Share on other sites

There a various ways for sending additional information along with the images.

And you can configure plupload to only upload on button click.

using multipart_params:

http://stackoverflow.com/questions/9535462/how-to-send-additional-data-using-plupload

more:

https://www.google.com/search?q=plupload+submit+additional+data&hl=de&gws_rd=ssl

the uploader.start(); in uploader.bind('FilesAdded'.. event is starting the upload

for example this is part of the events example on plupload.com

document.getElementById('uploadfiles').onclick = function() {
   uploader.start();
   return false;
}; 

So you don't need to split the form or anything..  ;)

EDIT: By the way, pluploader isn't using your file field at all. By this it's bypassing some limitations of it. So your files are directly uploaded using XmlHttpRequest, they just name the post request like your file field for convenience ;-)

And this is no matter you queue them and hit upload for all or let them upload automatically one by one..

So you could hide the file field for people with javascript enabled

Edited by Can
  • Like 1
Link to comment
Share on other sites

It's working now! :frantics:

Thank you very much Can and LostKobrakai!!!

I splited the form in two steps. That was easier for me. And i did not save the form to pages.

The files are stored on the server and our workflow system can get it.

Maybe it is not the best but for now it's working. I did a little start over.

This is now my site. On the first step i only validate the email field.

<!-- include head start -->
<?php include('./_head_pluploadtest.php'); ?>
<!-- include head end -->

<!-- include header start -->
<?php include('./_header.php'); ?>
<!-- include header end -->

<div id="basic-site-text" class="row content-box">
  <div class="large-12 columns"></div>
  <div class="medium-9 columns content-box-column-left">
<?php 

/**
 * ### Example front-end form template with file upload and fields ###
 *
 * - with files (images) upload to page field
 * - adds new page on the fly and adds uploaded images
 * - prevents CRSF attacks, this also prevents double post by refresh page after submit
 * - has required fields with error messages inline
 * - sanitizing and saving values to a page
 * - jquery example with disabled submit button on form submit
 *
 * Edit add or remove form markup below and configure this section according to what you need.
 *
 */

// ------------------------------ FORM Configuration ---------------------------------------

// --- Some default variables ---
$success_message   = "<div id='form-success-message' class='text-center'><i class='fi-check'></i><br><h4>Danke, Ihre Daten wurden übermittelt.</h4></div>";

// --- All form fields as nested array ---
// using html form field name => template field nam, from the page you're going to create
$form_fields = array(
    'email'               => array('type' => 'email', 'value' => '', 'required' => true)
);

// --- Page creation settings ---
$template           = "service-upload-files"; // the template used to create the page
$parent             = $pages->get("/service/pluploadtest/");
$page_fields        = array('email');

// $page_fields = define the fields (except file) you want to save value to a page
// this is for the form process to populate page fields.
// Your page template must have the same field names existent


// ------------------------------ FORM Processing ---------------------------------------

include("./form-plupload-test.php");

?>

<!-- ========================= FORM HTML markup  ================================== -->

<?php

/**
 * Some vars used on the form markup for error and population of fields
 *
 * $errors[fieldname]; to get errors
 * $form_fields[fieldname]['value'];
 *
 * Some helper function to get error markup
 * echo showError(string);
 *
 * Prevent CSRF attacks by adding hidden field with name and value
 * you an get by using $session->CSRF
 * $session->CSRF->getTokenName();
 * $session->CSRF->getTokenValue();
 *
 * $errors['csrf']; used to check for CSRF error
 *
 */

?>
   
<?php if(!$success) : ?>

    <?php if(!empty($errors)) echo showError("Die Form enthält Fehler!"); ?>
    <?php if(!empty($errors['csrf'])) echo showError($errors['csrf']); ?>

    <form name="myform" class="myform" id="fileUploadForm" method="post" action="./" enctype="multipart/form-data">

        <input type="hidden" name="<?php echo $session->CSRF->getTokenName(); ?>" value="<?php echo $session->CSRF->getTokenValue(); ?>"/>

        <div class=" <?php if(isset($errors['email'])) echo "error";?>">
            <label for="email">Ihre E-Mail Adresse: * </label>
            <input type="text" name="email" id="email" placeholder='max.mustermann@email.de' value="<?php 
            // zeigt die E-Mail Adresse des Users wenn eingeloggt.
            if($user->isLoggedin()) {
              if (empty($_POST["email"]))
                echo $user->email;
            }
            
            echo $sanitizer->entities($form_fields['email']['value']); ?>"/>
            <?php if(isset($errors['email'])) echo showError($errors['email']); ?>
        </div>

        <?php
      // if user is logged in... show some content specifically for logged-in users
              if ($user->isLoggedin()) {
               echo "<div class='callout secondary'>";
               echo $page->service_email_info_logged_in;
               echo "</div>";
              }
              else {
               echo "<div class='callout secondary'>";
               echo $page->service_email_info_logged_out;
               echo "</div>";
              }    
     ?>
        <div>
            <!--<div id="fileList"></div><br><br>-->
            <input type="hidden" name="action" id="action" value="send"/>
            <input data-toggle="loadingModal" type="submit" name="submit" id="submit" value="nächster Schritt" class="button service_button float-right"/>
        </div>
        
        <!-- Fehlermeldung plupload 
        <pre id="console"></pre>-->

	</form>

      <div class="full reveal" id="loadingModal" data-reveal>
        <div>
          <img src="<?php echo $config->urls->templates?>images/loading_circle.gif" alt="Intropsective Cage"><br>
        </div>
      </div>

<?php else: ?>

    <!-- <p><?php echo $success_message; ?></p> 
    <form id="fileUploadForm" method="post" action="./" enctype="multipart/form-data">
    	<div id="dropArea">
		<input class="dragDropFileUploadField" type="file" name="file[]" accept="jpg,jpeg,png,gif,mpg,mpeg,mp4,avi,wmv,mov,zip" multiple>
		<button type="submit" name="action" value="submit">Upload</button>
	</div>
    </form>

    <div id="fileList"></div>-->
    <form method="post" action="./" enctype="multipart/form-data">
      <div id="uploader">
		    <p>Your browser doesn't have Flash, Silverlight or HTML5 support.</p>
	    </div>
      <input type="submit" name="submit" id="submit" value="Absenden" class="button service_button"/>
    </form>

    <!-- <?php echo $_POST['email']; ?> -->
    <!-- übergibt die E-Mail Adresse an die nächste Seite -->
    <?php $session->newemail = $_POST['email']; ?>
  
<?php endif; ?> 

    </div><!-- Ende Container -->

  <div class="medium-3 columns content-box-column-right">
  	
  	
  </div>
</div>

<!-- include footer start -->
<?php include('./_foot.php'); ?>
<!-- include footer end -->

<!-- include footer start -->
<?php include('./_foot_service_pluploadtest.php'); ?>
<!-- include footer end -->

post-3507-0-01741100-1457025679_thumb.pn

On the second site i used pluploader with queue widget

post-3507-0-68659500-1457025750_thumb.pn

When i now add some files...

post-3507-0-68500700-1457025794_thumb.pn

the get uploaded if i hit the submit button

post-3507-0-01821000-1457025840_thumb.pn

And my xml files get generated with the email adress inside

post-3507-0-49319000-1457025877_thumb.pn

Form validation:

<?php
// ------------------------------ FORM Processing ---------------------------------------

$errors            = null;
$success           = false;

// helper function to format form errors
function showError($e){
    return "<div class='alert callout'><p class='error'>$e</p></div>";
}

// dump some variables
// var_dump($_FILES,$_POST,$_SESSION);

/**
 * Cast and save field values in array $form_fields
 * this is also done even form not submited to make populating the form later easier.
 *
 * Also used for pupulating page when form was valid
 */
$required_fields = array();
foreach($form_fields as $key => $f){
    if($f['type'] == 'email'){
        $form_fields[$key]['value'] = $sanitizer->email($input->post->$key);
    }
    // store required fields in array
    if($f['required']) $required_fields[] = $key;
}

/**
 * form was submitted, start processing the form
 */

if($input->post->action == 'send'){

    // validate CSRF token first to check if it's a valid request
    if(!$session->CSRF->hasValidToken()){
        $errors['csrf'] = "Die Formulardaten wurden nicht richtig ausgefüllt. Bitte versuchen Sie es erneut.";
    }

    /**
     * Ceck for required fields and make sure they have a value
     */
    foreach($required_fields as $req){

        // reqired text fields
        } if($form_fields[$req]['type'] == 'email'){
            if(!strlen($form_fields[$req]['value'])){
                $errors[$req] = "Bitte geben Sie Ihre E-Mail Adresse an.";
            }
    }

    /*
     * if no required errors found yet continue file upload form processing
     *
    if(empty($errors)) {

            // create the new page to add field values and uploaded images
            $uploadpage = new Page();
            $uploadpage->template = $template;
            $uploadpage->parent = $parent;

            // add title/name and make it unique with time and uniqid
            $uploadpage->title = date("d-m-Y H:i:s") . " - " . uniqid();

            // populate page fields with values using $page_fields array
            foreach($page_fields as $pf){
                if($templates->get($template)->hasField($pf)){
                    $uploadpage->$pf = $form_fields[$pf]['value'];
                } else {
                    throw new WireException("Template '$template' has no field: $pf");
                }
            }

            // RC: for safety, only add user uploaded files to an unpublished page, for later approval
            // RC: also ensure that using v2.3+, and $config->pagefileSecure=true; in your /site/config.php
            $uploadpage->addStatus(Page::statusUnpublished);
            $uploadpage->save(); */

            // $success_message .= "<p>Page created: <a href='$uploadpage->url'>$uploadpage->title</a></p>";
            $success = true;

            // reset the token so no double posts happen
            // also prevent submit button to from double clicking is a good pratice
            $session->CSRF->resetToken(); 
/*
    }*/}

the upload handler for plupload:

<?php
// --- WireUpload settings ---
$upload_path        = $config->paths->assets . "files/service_upload_files/pluploadtest/"; // tmp upload folder
$file_extensions    = array('jpg', 'jpeg', 'gif', 'png', 'tif', 'tiff');
$max_files          = 0;
$max_upload_size    = 1*14336*14336; // make sure PHP's upload and post max size is also set to a reasonable size 1*102400 = 100 MB
$overwrite          = false;
$newemail           = $session->newemail;

// RC: create temp path if it isn't there already
        if(!is_dir($upload_path)) {
            if(!wireMkdir($upload_path)) throw new WireException("No upload path!");
        }

        // setup new wire upload
        $u = new WireUpload('file');
        $u->setMaxFiles($max_files);
        $u->setMaxFileSize($max_upload_size);
        $u->setOverwrite($overwrite);
        $u->setDestinationPath($upload_path);
        $u->setValidExtensions($file_extensions);

        // start the upload of the files
        $files = $u->execute();

        // create XML files for switch

            // remove extension from files
            $withoutExt = preg_replace('/\\.[^.\\s]{3,4}$/', '', $files);
            
            foreach($withoutExt as $withoutExt_string) { 

            $doc = new DOMDocument('1.0');
            // we want a nice output
            $doc->formatOutput = true;

            $root = $doc->createElement('phpemail');
            $root = $doc->appendChild($root);

            $email = $doc->createElement('email');
            $email = $root->appendChild($email);

            $text = $doc->createTextNode($newemail);
            $text = $email->appendChild($text);

            $doc->save($upload_path . $withoutExt_string . ".xml");
            
            }


?>

And the plupload config in my footer:

<!-- jQuery first, then foundation JS. -->
    <script src="<?php echo $config->urls->templates?>scripts/vendor/jquery.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/vendor/what-input.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/foundation.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/app.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/onchange_dropdown_service.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/email_service_validation.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/plupload.full.min.js"></script>
    <script src="<?php echo $config->urls->templates?>scripts/jquery.plupload.queue.js"></script>
    <script src="<?php echo $config->urls->templates?>langs/de.js"></script>
    <script type="text/javascript">
$(function() {
    
    // Setup html5 version
    $("#uploader").pluploadQueue({
        // General settings
        runtimes : 'html5,flash,silverlight,html4',
        url : 'uploadplupload/',
        //chunk_size: '1mb',
        unique_names: false,
        rename : true,
        dragdrop: true,
        
        filters : {
            // Maximum file size
            max_file_size : '200mb',
            // Specify what files to browse for
            mime_types: [
                {title : "Image files", extensions : "jpg,jpeg,gif,png,tif,tiff"}
            ]
        },

        // max file restriction with errors
        init : {
        FilesAdded: function(up, files) {
          var max_files = 3;
          plupload.each(files, function(file) {
            if (up.files.length > max_files) {
              alert('Sie dürfen bei einem Durchgang nur ' + max_files + ' Dateien hochladen.');
              up.removeFile(file);
            }
          });
          if (up.files.length >= max_files) {
            $('#pickfiles').hide('slow');
          }
        },
        FilesRemoved: function(up, files) {
          if (up.files.length < max_files) {
            $('#pickfiles').fadeIn('slow');
          }
        }
      },

        // Resize images on clientside if we can
        //resize : {width : 320, height : 240, quality : 90},

        flash_swf_url : '../../js/Moxie.swf',
        silverlight_xap_url : '../../js/Moxie.xap'
    });

    // start file upload ob drop
    //var uploader = $("#uploader").pluploadQueue();
    //uploader.bind('FilesAdded', function(up, files) {
    //uploader.start();
    //});

    // Client side form validation
    // uploads the files in queue and submits the form
    $("form").submit(function(e) {
        var uploader = $("#uploader").pluploadQueue();

        // Validate number of uploaded files
        if (uploader.total.uploaded == 0) {
            // Files in queue upload them first
            if (uploader.files.length > 0) {
                // When all files are uploaded submit form
                uploader.bind("StateChanged", function() {
                    if (uploader.total.uploaded == uploader.files.length)
                        $("form").submit();
                });

                uploader.start();
            } else
                alert("Sie müssen mindestens eine Datei auswählen.");

            e.preventDefault();
        }
    });

});
</script>
<noscript><p><img src="//piwik-gbd.de/piwik.php?idsite=5" style="border:0;" alt="" /></p></noscript>
<!-- End Piwik Code -->
  </body>
</html>

I will made a step by step tutorial. This becomes too big. Maybe i can improve something.

But for now it works! :) :) :)

  • Like 2
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...