user26676 user26676 - 1 month ago 7
MySQL Question

jQuery-File-Upload doesn't work : PHP jQuery - correct dependancies missing

Hi I like the look of the jQuery-File-Upload plugin but it's insane how hard it is to remove the fluff code from the good bits.. it seems intent on forcing stuff down my throat to work.

simply put it works when not part of my code but breaks when I implement it outside of itself

EG:


  • the index.html example is RIDDLED with external url references I don' want / can't use in my actual code. When I cut it out and attempt to lean it out it breaks and there is too much to pour through.

  • the documentation starts far too "deep" into the process for an actual develop who knows what he wants - there are no "simple" examples there are "assumptive" examples based on assuming your context.

  • can someone help me with an index.php of my own that tells me how in as simple and light way as possible how to target an actual php file where I put it, what params are sent (for any subsequent db updating I might do) where to nominate the upload dir in the settings, how to do anything "normal" is hidden.. First principles are always best, but they are absent.

  • simply put: I want to replace the normal "file_upload" htmlform scenario with the nice gui version from jQuery-File-Upload but it's too hard by half!



WHERE ARE THE REAL BITS OF CODE!

and before I get lectured this is the 3rd or 4th attempt to implement this over about 9 months and I have stopped after ~ 4 hours on each installation. each other time I have backed off and gone with something less pretty but that I can control properly.

<!-- Force latest IE rendering engine or ChromeFrame if installed -->
<!--[if IE]>
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<![endif]-->

<!-- Generic page styles -->
<link rel="stylesheet" href="../common/jQuery-File-Upload_8.7.1/css/style.css">
<!-- CSS to style the file input field as button and adjust the Bootstrap progress bars -->
<link rel="stylesheet" href="../common/jQuery-File-Upload_8.7.1/css/jquery.fileupload-ui.css">

<div class="container">

<!-- The file upload form used as target for the file upload widget -->
<form id="fileupload" action="//jquery-file-upload.appspot.com/" method="POST" enctype="multipart/form-data">

<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="row fileupload-buttonbar">
<div class="span7">
<!-- The fileinput-button span is used to style the file input field as button -->
<span class="btn btn-success fileinput-button">
<i class="icon-plus icon-white"></i>
<span>Add files...</span>
<input type="file" name="files[]" multiple>
</span>
<button type="submit" class="btn btn-primary start">
<i class="icon-upload icon-white"></i>
<span>Start upload</span>
</button>
<button type="reset" class="btn btn-warning cancel">
<i class="icon-ban-circle icon-white"></i>
<span>Cancel upload</span>
</button>
<button type="button" class="btn btn-danger delete">
<i class="icon-trash icon-white"></i>
<span>Delete</span>
</button>
<input type="checkbox" class="toggle">
<!-- The loading indicator is shown during file processing -->
<span class="fileupload-loading"></span>
</div>
<!-- The global progress information -->
<div class="span5 fileupload-progress fade">
<!-- The global progress bar -->
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
<div class="bar" style="width:0%;"></div>
</div>
<!-- The extended global progress information -->
<div class="progress-extended">&nbsp;</div>
</div>
</div>
<!-- The table listing the files available for upload/download -->
<table role="presentation" class="table table-striped"><tbody class="files"></tbody></table>
</form>
<br>
</div>
<!-- The blueimp Gallery widget -->
<div id="blueimp-gallery" class="blueimp-gallery blueimp-gallery-controls" data-filter=":even">
<div class="slides"></div>
<h3 class="title"></h3>
<a class="prev">‹</a>
<a class="next">›</a>
<a class="close">×</a>
<a class="play-pause"></a>
<ol class="indicator"></ol>
</div>
<!-- The template to display files available for upload -->
<script id="template-upload" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-upload fade">
<td>
<span class="preview"></span>
</td>
<td>
<p class="name">{%=file.name%}</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<p class="size">{%=o.formatFileSize(file.size)%}</p>
{% if (!o.files.error) { %}
<div class="progress progress-success progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0"><div class="bar" style="width:0%;"></div></div>
{% } %}
</td>
<td>
{% if (!o.files.error && !i && !o.options.autoUpload) { %}
<button class="btn btn-primary start">
<i class="icon-upload icon-white"></i>
<span>Start</span>
</button>
{% } %}
{% if (!i) { %}
<button class="btn btn-warning cancel">
<i class="icon-ban-circle icon-white"></i>
<span>Cancel</span>
</button>
{% } %}
</td>
</tr>
{% } %}
</script>
<!-- The template to display files available for download -->
<script id="template-download" type="text/x-tmpl">
{% for (var i=0, file; file=o.files[i]; i++) { %}
<tr class="template-download fade">
<td>
<span class="preview">
{% if (file.thumbnailUrl) { %}
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" data-gallery><img src="{%=file.thumbnailUrl%}"></a>
{% } %}
</span>
</td>
<td>
<p class="name">
<a href="{%=file.url%}" title="{%=file.name%}" download="{%=file.name%}" {%=file.thumbnailUrl?'data-gallery':''%}>{%=file.name%}</a>
</p>
{% if (file.error) { %}
<div><span class="label label-important">Error</span> {%=file.error%}</div>
{% } %}
</td>
<td>
<span class="size">{%=o.formatFileSize(file.size)%}</span>
</td>
<td>
<button class="btn btn-danger delete" data-type="{%=file.deleteType%}" data-url="{%=file.deleteUrl%}"{% if (file.deleteWithCredentials) { %} data-xhr-fields='{"withCredentials":true}'{% } %}>
<i class="icon-trash icon-white"></i>
<span>Delete</span>
</button>
<input type="checkbox" name="delete" value="1" class="toggle">
</td>
</tr>
{% } %}
</script>

<!-- The Iframe Transport is required for browsers without support for XHR file uploads -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.iframe-transport.js"></script>
<!-- The basic File Upload plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.ui.widget.js"></script>
<!-- The basic File Upload plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload.js"></script>
<!-- The File Upload processing plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-process.js"></script>
<!-- The File Upload image preview & resize plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-image.js"></script>
<!-- The File Upload audio preview plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-audio.js"></script>
<!-- The File Upload video preview plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-video.js"></script>
<!-- The File Upload validation plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-validate.js"></script>
<!-- The File Upload user interface plugin -->
<script src="../common/jQuery-File-Upload_8.7.1/js/jquery.fileupload-ui.js"></script>
<!-- The main application script -->
<script src="../common/jQuery-File-Upload_8.7.1/js/main.js"></script>
<!-- The XDomainRequest Transport is included for cross-domain file deletion for IE 8 and IE 9 -->
<!--[if (gte IE 8)&(lt IE 10)]>
<script src="../common/jQuery-File-Upload_8.7.1/js/cors/jquery.xdr-transport.js"></script>
<![endif]-->

Answer

So I've been pulling hair out for just over a week with this one and I feel your pain. I managed to get something working though, and I'm planning to write a proper step-by-step article/blog post about this somewhere as I struggled to find much useful information.

How I managed to eventually properly implement this, was by implementing the basic plugin, and building the rest of the user interface manually. My requirements were for a multi-file upload with additional form fields for each upload.

When using the basic plugin, be sure to save yourself the time and grab the template engine that they use in the UI version (one of the external URL references you mentioned) as it really helps to have a template that you want to load for each upload.

The JS files that you would need are as follows:

  • jquery.ui.widget.js
  • jquery.iframe-transport.js
  • jquery.fileupload.js
  • tmpl.min.js (if you plan on using the template engine)

Here is my html for the file upload:

<div class="row-fluid">
    <input type="file" name="files[]" id="fileupload" multiple="multiple" data-url="uploader.php"/>
</div>

<!-- the file uploads will be shown here -->
<div id="uploads" class="row-fluid"></div>

<!-- template for each file being uploaded -->
<script type="text/x-tmpl" id="upload-template">
    <div class="span4" style="padding: 10px;">
        <div class="preview"></div>

        <div class="control-group">
            <label class="control-label" for="title">{$lang.video}</label>
            <div class="controls">
                <input type="text" name="title" value="{%=o.title%}"/>
            </div>
        </div>

        <div class="control-group">
            <div class="controls">
                <button class="btn btn-primary start">
                    <i class="icon-upload"></i>
                    <span>start upload</span>
                </button>
                <button class="btn btn-warning cancel">
                    <i class="icon-remove"></i>
                    <span>cancel</span>
                </button>
            </div>
        </div>
    </div>
</script>

Then, my custom JS implementation:

$(function() {
    // initialize the jQuery file upload plugin
    var $fileuploadInput = $("#fileupload"); // used to clear the value
    $fileuploadInput.fileupload({
    autoUpload: false,
    add: function(e, data) {
        // add each selected file
        $.each(data.files, function(index, file) {
            // initialize the upload and attach to upload context
            var fileData = {
                title: file.name
            };
            var $upload = $(tmpl("upload-template", fileData));
            data.context = $upload;
            var $uploadRequest;

            // add click handlers for the start and cancel buttons
            var $startButton = $upload.find('button.start');
            $startButton.off('click');
            $startButton.on('click', function() {
                // add progress bar
                $upload.append('<div class="progress progress-striped active"><div class="bar" style="width:0%;font-weight:bold;"></div></div>');

                data.formData = {
                    title: $upload.find('input[name="title"]').val()
                };
                $uploadRequest = data.submit()
                        .success(function(response) {
                            console.log('upload successful');
                        }
                        else {
                            // re-enable the button
                                $startButton.removeClass('disabled');
                            }
                        })
                        .error(function() {
                            $startButton.removeClass('disabled');
                        })
                        .complete(function() {});
                $startButton.addClass('disabled');
            });
            // abort the jqXHR request object (upload) when cancel button is clicked
            var $cancelButton = $upload.find('button.cancel');
            $cancelButton.off('click');
            $cancelButton.on('click', function() {
                if ($uploadRequest) {
                    $uploadRequest.abort();
                }
                $upload.remove();
            });
            $("#uploads").append($upload);

            // add video preview
            var video = document.createElement('video');
            video.src = URL.createObjectURL(file);
            video.controls = true;
            $upload.find('.preview').append(video);
        });
    },
    progress: function(e, data) {
        var progress = parseInt(data.loaded / data.total * 100, 10);
        data.context
                .find('.progress .bar')
                .css('width', progress+'%')
                .text(progress+'%');
    },
    done: function(e, data) {
        data.context
                .find('.progress')
                .removeClass('active')
                .removeClass('progress-striped')
                .addClass('progress-success')
                .find('.bar')
                .css('width', '100%')
                .text('Upload Complete');
    },
    stop: function(e, data) {
        console.log('upload stopped');
    }
});
});

At your receiving PHP file, you will receive a POST request so all the fields set in the data.formData should be available with $_POST there and $_FILES output (var_dump) looks as follows:

array(1) {
  ["files"]=>
  array(5) {
    ["name"]=>
    array(1) {
      [0]=>
      string(12) "6a19440e.mp4"
    }
    ["type"]=>
    array(1) {
      [0]=>
      string(9) "video/mp4"
    }
    ["tmp_name"]=>
    array(1) {
      [0]=>
      string(23) "C:\xampp\tmp\phpEED.tmp"
    }
    ["error"]=>
    array(1) {
      [0]=>
      int(0)
    }
    ["size"]=>
    array(1) {
      [0]=>
      int(6068582)
    }
  }
}

The rest of the file upload you would handle normally. This is still a work in progress for me. I'll update to a fully working script on request as soon as I've finished this implementation.

Comments