Can someone explain how to implement the jQuery File Upload plugin?

JqueryFile UploadJquery PluginsJquery File-Upload

Jquery Problem Overview


EDIT (Oct 2019):

6 years later and jQuery File Upload is clearly still driving folks insane. If you're finding little solace in the answers here, try a search of NPM for a modern alternative. It's not worth the hassle, I promise.

I recommended Uploadify in the previous edit but, as a commenter pointed out, they no longer appear to offer a free version. Uploadify was so 2013 anyway.


EDIT:
This still seems to be getting traffic so I'll explain what I ended up doing. I eventually got the plugin working by following the tutorial in the accepted answer. However, jQuery File Upload is a real hassle and if you're looking for a simpler file upload plugin, I would highly recommend Uploadify. As an answer pointed out, it is only free for non-commercial use.


Background

I'm trying to use blueimp's jQuery File Upload to allow users to upload files. Out of the box it works perfectly, following the setup instructions. But to use it practically on my website, I want to be able to do a couple of things:

  • Include the uploader on any of my existing pages
  • Change the directory for uploaded files

All the files for the plugin are located in a folder under the root.

I've tried...

  • Moving the demo page into the root and updating the paths for the necessary scripts
  • Changing the 'upload_dir' and 'upload_url' options in the UploadHandler.php file as suggested here.
  • Changing the URL in the second line of the demo javascript

In all cases, the preview shows, and the progress bar runs, but the files fail to upload, and I get this error in the console: Uncaught TypeError: Cannot read property 'files' of undefined. I don't understand how all the parts of the plugin work which is making it difficult to debug.

Code

The javascript in the demo page:

$(function () {
'use strict';
// Change this to the location of your server-side upload handler:
var url = 'file_upload/server/php/UploadHandler.php',
    uploadButton = $('<button/>')
        .addClass('btn')
        .prop('disabled', true)
        .text('Processing...')
        .on('click', function () {
            var $this = $(this),
                data = $this.data();
            $this
                .off('click')
                .text('Abort')
                .on('click', function () {
                    $this.remove();
                    data.abort();
                });
            data.submit().always(function () {
                $this.remove();
            });
        });
$('#fileupload').fileupload({
    url: url,
    dataType: 'json',
    autoUpload: false,
    acceptFileTypes: /(\.|\/)(gif|jpe?g|png)$/i,
    maxFileSize: 5000000, // 5 MB
    // Enable image resizing, except for Android and Opera,
    // which actually support image resizing, but fail to
    // send Blob objects via XHR requests:
    disableImageResize: /Android(?!.*Chrome)|Opera/
        .test(window.navigator.userAgent),
    previewMaxWidth: 100,
    previewMaxHeight: 100,
    previewCrop: true
}).on('fileuploadadd', function (e, data) {
    data.context = $('<div/>').appendTo('#files');
    $.each(data.files, function (index, file) {
        var node = $('<p/>')
                .append($('<span/>').text(file.name));
        if (!index) {
            node
                .append('<br>')
                .append(uploadButton.clone(true).data(data));
        }
        node.appendTo(data.context);
    });
}).on('fileuploadprocessalways', function (e, data) {
    var index = data.index,
        file = data.files[index],
        node = $(data.context.children()[index]);
    if (file.preview) {
        node
            .prepend('<br>')
            .prepend(file.preview);
    }
    if (file.error) {
        node
            .append('<br>')
            .append(file.error);
    }
    if (index + 1 === data.files.length) {
        data.context.find('button')
            .text('Upload')
            .prop('disabled', !!data.files.error);
    }
}).on('fileuploadprogressall', function (e, data) {
    var progress = parseInt(data.loaded / data.total * 100, 10);
    $('#progress .bar').css(
        'width',
        progress + '%'
    );
}).on('fileuploaddone', function (e, data) {
    $.each(data.result.files, function (index, file) {
        var link = $('<a>')
            .attr('target', '_blank')
            .prop('href', file.url);
        $(data.context.children()[index])
            .wrap(link);
    });
}).on('fileuploadfail', function (e, data) {
    $.each(data.result.files, function (index, file) {
        var error = $('<span/>').text(file.error);
        $(data.context.children()[index])
            .append('<br>')
            .append(error);
    });
}).prop('disabled', !$.support.fileInput)
    .parent().addClass($.support.fileInput ? undefined : 'disabled');
});


I'm surprised by the lack of documentation; it seems like it should be a simple thing to change. I would appreciate if someone could explain how to do this.

Jquery Solutions


Solution 1 - Jquery

I was looking for a similar functionality some days back and came across a good tutorial on tutorialzine. Here is an working example. Complete tutorial can be found here.

Simple form to hold the file upload dialogue:

<form id="upload" method="post" action="upload.php" enctype="multipart/form-data">
  <input type="file" name="uploadctl" multiple />
  <ul id="fileList">
    <!-- The file list will be shown here -->
  </ul>
</form>

And here is the jQuery code to upload the files:

$('#upload').fileupload({

  // This function is called when a file is added to the queue
  add: function (e, data) {
    //This area will contain file list and progress information.
    var tpl = $('<li class="working">'+
                '<input type="text" value="0" data-width="48" data-height="48" data-fgColor="#0788a5" data-readOnly="1" data-bgColor="#3e4043" />'+
                '<p></p><span></span></li>' );

    // Append the file name and file size
    tpl.find('p').text(data.files[0].name)
                 .append('<i>' + formatFileSize(data.files[0].size) + '</i>');

    // Add the HTML to the UL element
    data.context = tpl.appendTo(ul);

    // Initialize the knob plugin. This part can be ignored, if you are showing progress in some other way.
    tpl.find('input').knob();

    // Listen for clicks on the cancel icon
    tpl.find('span').click(function(){
      if(tpl.hasClass('working')){
              jqXHR.abort();
      }
      tpl.fadeOut(function(){
              tpl.remove();
      });
    });

    // Automatically upload the file once it is added to the queue
    var jqXHR = data.submit();
  },
  progress: function(e, data){

        // Calculate the completion percentage of the upload
        var progress = parseInt(data.loaded / data.total * 100, 10);

        // Update the hidden input field and trigger a change
        // so that the jQuery knob plugin knows to update the dial
        data.context.find('input').val(progress).change();

        if(progress == 100){
            data.context.removeClass('working');
        }
    }
});
//Helper function for calculation of progress
function formatFileSize(bytes) {
    if (typeof bytes !== 'number') {
        return '';
    }

    if (bytes >= 1000000000) {
        return (bytes / 1000000000).toFixed(2) + ' GB';
    }

    if (bytes >= 1000000) {
        return (bytes / 1000000).toFixed(2) + ' MB';
    }
    return (bytes / 1000).toFixed(2) + ' KB';
}

And here is the PHP code sample to process the data:

if($_POST) {
    $allowed = array('jpg', 'jpeg');

    if(isset($_FILES['uploadctl']) && $_FILES['uploadctl']['error'] == 0){
    
        $extension = pathinfo($_FILES['uploadctl']['name'], PATHINFO_EXTENSION);
        
        if(!in_array(strtolower($extension), $allowed)){
            echo '{"status":"error"}';
            exit;
        }
        
        if(move_uploaded_file($_FILES['uploadctl']['tmp_name'], "/yourpath/." . $extension)){
            echo '{"status":"success"}';
            exit;
        }
        echo '{"status":"error"}';
    }
    exit();
}

The above code can be added to any existing form. This program automatically uploads images, once they are added. This functionality can be changed and you can submit the image, while you are submitting your existing form.

Updated my answer with actual code. All credits to original author of the code.

Source: http://tutorialzine.com/2013/05/mini-ajax-file-upload-form/

Solution 2 - Jquery

I've just spent 2 hours battling with jQuery Upload but gave up because of the amount of dependencies (I had 13 JS files included to get all the bells and whistles).

I did a bit more searching and came across a neat project called Dropzone.js, which does not have any dependencies.

The author has also created a bootstrap demo which was inspired by the jQuery File Upload plugin.

I hope this saves someone else some time.

Solution 3 - Jquery

I also struggled with this but got it working once I figured out how the paths work in UploadHandler.php: upload_dir and upload_url are about the only settings to look at to get it working. Also check your server error logs for debugging information.

Solution 4 - Jquery

Check out the Image drag and drop uploader with image preview using dropper jquery plugin.

HTML

<div class="target" width="78" height="100"><img /></div>

JS

$(".target").dropper({
	action: "upload.php",

}).on("start.dropper", onStart);
function onStart(e, files){
console.log(files[0]);
   
    image_preview(files[0].file).then(function(res){
$('.dropper-dropzone').empty();
//$('.dropper-dropzone').css("background-image",res.data);
 $('#imgPreview').remove();        
$('.dropper-dropzone').append('<img id="imgPreview"/><span style="display:none">Drag and drop files or click to select</span>');
var widthImg=$('.dropper-dropzone').attr('width');
        $('#imgPreview').attr({width:widthImg});
    $('#imgPreview').attr({src:res.data});

    })
    
}

function image_preview(file){
    var def = new $.Deferred();
    var imgURL = '';
    if (file.type.match('image.*')) {
        //create object url support
        var URL = window.URL || window.webkitURL;
        if (URL !== undefined) {
            imgURL = URL.createObjectURL(file);
            URL.revokeObjectURL(file);
            def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
        }
        //file reader support
        else if(window.File && window.FileReader)
        {
            var reader = new FileReader();
            reader.readAsDataURL(file);
            reader.onloadend = function () {
                imgURL = reader.result;
                def.resolve({status: 200, message: 'OK', data:imgURL, error: {}});
            }
        }
        else {
            def.reject({status: 1001, message: 'File uploader not supported', data:imgURL, error: {}});
        }
    }
    else
        def.reject({status: 1002, message: 'File type not supported', error: {}});
    return def.promise();
}

$('.dropper-dropzone').mouseenter(function() {
 $( '.dropper-dropzone>span' ).css("display", "block");
});

$('.dropper-dropzone').mouseleave(function() {
 $( '.dropper-dropzone>span' ).css("display", "none");
});
 

CSS

.dropper-dropzone{
    width:78px;
padding:3px;
    height:100px;
position: relative;
}
.dropper-dropzone>img{
    width:78px;
    height:100px;
margin-top=0;
}

.dropper-dropzone>span {
    position: absolute;
    right: 10px;
    top: 20px;
color:#ccc;


}

.dropper .dropper-dropzone{
    
padding:3px !important    
}

Demo Jsfiddle

Solution 5 - Jquery

This is good Angular plugin for uploading files, and its free!

angular file upload

Solution 6 - Jquery

I struggled with this plugin for a while on Rails, and then someone gemified it obsoleting all the code I had created.

Although it looks like you're not using this in Rails, however if anyone is using it checkout this gem. The source is here --> jQueryFileUpload Rails.

Update:

In order to satisfy the commenter I've updated my answer. Essentially "use this gem, here is the source code" If it disappears then do it the long way.

Solution 7 - Jquery

Hi try bellow link it is very easy. I've been stuck for long time and it solve my issue in few minutes. http://simpleupload.michaelcbrook.com/#examples

Solution 8 - Jquery

Droply.js is perfect for this. It's simple and comes pre-packaged with a demo site that works out of the box.

Solution 9 - Jquery

it's 2021 and here's a fantastically easy plugin to upload anything:

https://pqina.nl/filepond/?ref=pqina

add your element:

<input type="file" 
class="filepond"
name="filepond" 
multiple 
data-allow-reorder="true"
data-max-file-size="3MB"
data-max-files="3">

Register any additional plugins:

  FilePond.registerPlugin(
FilePondPluginImagePreview,  
FilePondPluginImageExifOrientation,  
FilePondPluginFileValidateSize,  
FilePondPluginImageEdit);

Then wire in the element:

// Select the file input and use 
// create() to turn it into a pond
FilePond.create(
  document.querySelector('input'),

  // Use Doka.js as image editor
  imageEditEditor: Doka.create({
    utils: ['crop', 'filter', 'color']
  })
);

I use this with the additional Doka image editor to upload and transform images at https://www.yoodu.co.uk

crazy simple to setup and the guys who run it are great at support.

As you can tell I'm a fanboy.

Solution 10 - Jquery

You can use uploadify this is the best multiupload jquery plugin i have used.

The implementation is easy, the browser support is perfect.

Solution 11 - Jquery

For the UI plugin, with jsp page and Spring MVC..

Sample html. Needs to be within a form element with an id attribute of fileupload

	<!-- The fileupload-buttonbar contains buttons to add/delete files and start/cancel the upload -->
<div class="fileupload-buttonbar">
	<div>
		<!-- The fileinput-button span is used to style the file input field as button -->
		<span class="btn btn-success fileinput-button">
			<i class="glyphicon glyphicon-plus"></i>
			<span>Add files</span>
			<input id="fileuploadInput" type="file" name="files[]" multiple>
		</span>
		<%-- https://stackoverflow.com/questions/925334/how-is-the-default-submit-button-on-an-html-form-determined --%>
		<button type="button" class="btn btn-primary start">
			<i class="glyphicon glyphicon-upload"></i>
			<span>Start upload</span>
		</button>
		<button type="reset" class="btn btn-warning cancel">
			<i class="glyphicon glyphicon-ban-circle"></i>
			<span>Cancel upload</span>
		</button>
		<!-- The global file processing state -->
		<span class="fileupload-process"></span>
	</div>
	<!-- The global progress state -->
	<div class="fileupload-progress fade">
		<!-- The global progress bar -->
		<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100">
			<div class="progress-bar progress-bar-success" style="width:0%;"></div>
		</div>
		<!-- The extended global progress state -->
		<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>

<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/css/jquery.fileupload.css">
<link rel="stylesheet" type="text/css" href="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/css/jquery.fileupload-ui.css">

<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/vendor/jquery.ui.widget.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.iframe-transport.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-process.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-validate.js"></script>
<script type="text/javascript" src="${pageContext.request.contextPath}/js/jquery-file-upload-9.14.2/js/jquery.fileupload-ui.js"></script>

<script type="text/javascript">
	$(document).ready(function () {
			var maxFileSizeBytes = ${maxFileSizeBytes};
		if (maxFileSizeBytes < 0) {
			//-1 or any negative value means no size limit
			//set to undefined
			//https://stackoverflow.com/questions/5795936/how-to-set-a-javascript-var-as-undefined
			maxFileSizeBytes = void 0;
		}

		//https://github.com/blueimp/jQuery-File-Upload/wiki/Options
		//https://stackoverflow.com/questions/34063348/jquery-file-upload-basic-plus-ui-and-i18n
		//https://stackoverflow.com/questions/11337897/how-to-customize-upload-download-template-of-blueimp-jquery-file-upload
		$('#fileupload').fileupload({
			url: '${pageContext.request.contextPath}/app/uploadResources.do',
			fileInput: $('#fileuploadInput'),
			acceptFileTypes: /(\.|\/)(jrxml|png|jpe?g)$/i,
			maxFileSize: maxFileSizeBytes,
			messages: {
				acceptFileTypes: '${fileTypeNotAllowedText}',
				maxFileSize: '${fileTooLargeMBText}'
			},
			filesContainer: $('.files'),
			uploadTemplateId: null,
			downloadTemplateId: null,
			uploadTemplate: function (o) {
				var rows = $();
				$.each(o.files, function (index, file) {
					var row = $('<tr class="template-upload fade">' +
							'<td><p class="name"></p>' +
							'<strong class="error text-danger"></strong>' +
							'</td>' +
							'<td><p class="size"></p>' +
							'<div class="progress progress-striped active" role="progressbar" aria-valuemin="0" aria-valuemax="100" aria-valuenow="0">' +
							'<div class="progress-bar progress-bar-success" style="width:0%;"></div></div>' +
							'</td>' +
							'<td>' +
							(!index && !o.options.autoUpload ?
									'<button class="btn btn-primary start" disabled>' +
									'<i class="glyphicon glyphicon-upload"></i> ' +
									'<span>${startText}</span>' +
									'</button>' : '') +
							(!index ? '<button class="btn btn-warning cancel">' +
									'<i class="glyphicon glyphicon-ban-circle"></i> ' +
									'<span>${cancelText}</span>' +
									'</button>' : '') +
							'</td>' +
							'</tr>');
					row.find('.name').text(file.name);
					row.find('.size').text(o.formatFileSize(file.size));
					if (file.error) {
						row.find('.error').text(file.error);
					}
					rows = rows.add(row);
				});
				return rows;
			},
			downloadTemplate: function (o) {
				var rows = $();
				$.each(o.files, function (index, file) {
					var row = $('<tr class="template-download fade">' +
							'<td><p class="name"></p>' +
							(file.error ? '<strong class="error text-danger"></strong>' : '') +
							'</td>' +
							'<td><span class="size"></span></td>' +
							'<td>' +
							(file.deleteUrl ? '<button class="btn btn-danger delete">' +
									'<i class="glyphicon glyphicon-trash"></i> ' +
									'<span>${deleteText}</span>' +
									'</button>' : '') +
							'<button class="btn btn-warning cancel">' +
							'<i class="glyphicon glyphicon-ban-circle"></i> ' +
							'<span>${clearText}</span>' +
							'</button>' +
							'</td>' +
							'</tr>');
					row.find('.name').text(file.name);
					row.find('.size').text(o.formatFileSize(file.size));
					if (file.error) {
						row.find('.error').text(file.error);
					}
					if (file.deleteUrl) {
						row.find('button.delete')
								.attr('data-type', file.deleteType)
								.attr('data-url', file.deleteUrl);
					}
					rows = rows.add(row);
				});
				return rows;
			}
		});

	});
</script>

Sample upload and delete request handlers

	@PostMapping("/app/uploadResources")
public @ResponseBody
Map<String, List<FileUploadResponse>> uploadResources(MultipartHttpServletRequest request,
		Locale locale) {
	//https://github.com/jdmr/fileUpload/blob/master/src/main/java/org/davidmendoza/fileUpload/web/ImageController.java
	//https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
	Map<String, List<FileUploadResponse>> response = new HashMap<>();
	List<FileUploadResponse> fileList = new ArrayList<>();

	String deleteUrlBase = request.getContextPath() + "/app/deleteResources.do?filename=";

	//http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/MultipartRequest.html
	Iterator<String> itr = request.getFileNames();
	while (itr.hasNext()) {
		String htmlParamName = itr.next();
		MultipartFile file = request.getFile(htmlParamName);
		FileUploadResponse fileDetails = new FileUploadResponse();
		String filename = file.getOriginalFilename();
		fileDetails.setName(filename);
		fileDetails.setSize(file.getSize());
		try {
			String message = saveFile(file);
			if (message != null) {
				String errorMessage = messageSource.getMessage(message, null, locale);
				fileDetails.setError(errorMessage);
			} else {
				//save successful
				String encodedFilename = URLEncoder.encode(filename, "UTF-8");
				String deleteUrl = deleteUrlBase + encodedFilename;
				fileDetails.setDeleteUrl(deleteUrl);
			}
		} catch (IOException ex) {
			logger.error("Error", ex);
			fileDetails.setError(ex.getMessage());
		}

		fileList.add(fileDetails);
	}

	response.put("files", fileList);

	return response;
}

@PostMapping("/app/deleteResources")
public @ResponseBody
Map<String, List<Map<String, Boolean>>> deleteResources(@RequestParam("filename") List<String> filenames) {
	Map<String, List<Map<String, Boolean>>> response = new HashMap<>();
	List<Map<String, Boolean>> fileList = new ArrayList<>();

	String templatesPath = Config.getTemplatesPath();
	for (String filename : filenames) {
		Map<String, Boolean> fileDetails = new HashMap<>();
		
		String cleanFilename = ArtUtils.cleanFileName(filename);
		String filePath = templatesPath + cleanFilename;
		
		File file = new File(filePath);
		boolean deleted = file.delete();
		
		if (deleted) {
			fileDetails.put(cleanFilename, true);
		} else {
			fileDetails.put(cleanFilename, false);
		}
		
		fileList.add(fileDetails);
	}
	
	response.put("files", fileList);

	return response;
}

Sample class for generating the required json response

	public class FileUploadResponse {
	//https://github.com/blueimp/jQuery-File-Upload/wiki/Setup#using-jquery-file-upload-ui-version-with-a-custom-server-side-upload-handler
	
	private String name;
	private long size;
	private String error;
	private String deleteType = "POST";
	private String deleteUrl;

	/**
	 * @return the name
	 */
	public String getName() {
		return name;
	}

	/**
	 * @param name the name to set
	 */
	public void setName(String name) {
		this.name = name;
	}

	/**
	 * @return the size
	 */
	public long getSize() {
		return size;
	}

	/**
	 * @param size the size to set
	 */
	public void setSize(long size) {
		this.size = size;
	}

	/**
	 * @return the error
	 */
	public String getError() {
		return error;
	}

	/**
	 * @param error the error to set
	 */
	public void setError(String error) {
		this.error = error;
	}

	/**
	 * @return the deleteType
	 */
	public String getDeleteType() {
		return deleteType;
	}

	/**
	 * @param deleteType the deleteType to set
	 */
	public void setDeleteType(String deleteType) {
		this.deleteType = deleteType;
	}

	/**
	 * @return the deleteUrl
	 */
	public String getDeleteUrl() {
		return deleteUrl;
	}

	/**
	 * @param deleteUrl the deleteUrl to set
	 */
	public void setDeleteUrl(String deleteUrl) {
		this.deleteUrl = deleteUrl;
	}
	
}

See https://pitipata.blogspot.co.ke/2017/01/using-jquery-file-upload-ui.html

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionAustenView Question on Stackoverflow
Solution 1 - JquerySubrat PattnaikView Answer on Stackoverflow
Solution 2 - JqueryTimView Answer on Stackoverflow
Solution 3 - JqueryLouis FerreiraView Answer on Stackoverflow
Solution 4 - JquerytvshajeerView Answer on Stackoverflow
Solution 5 - JquerySahipView Answer on Stackoverflow
Solution 6 - JqueryengineerDaveView Answer on Stackoverflow
Solution 7 - JqueryIftikhar KhanView Answer on Stackoverflow
Solution 8 - JqueryGeremiaView Answer on Stackoverflow
Solution 9 - JqueryAlex StephensView Answer on Stackoverflow
Solution 10 - JqueryCORSAIRView Answer on Stackoverflow
Solution 11 - JqueryTimothy AnyonaView Answer on Stackoverflow