Created
January 13, 2014 11:38
-
-
Save dmitryevseev/8398865 to your computer and use it in GitHub Desktop.
File upload with drag&drop and FormData
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<label id="image_container">Upload image: | |
<div id="image_dropzone" | |
class="dropzone" | |
dropzone="copy file:image/png file:image/gif file:image/jpeg file:image/jpg file:image/jpe file:image/ico file:image/icon file:text/ico file:application/ico file:image/x-icon file:image/tiff file:image/tif file:image/x-windows-bmp file:image/bmp"> | |
<h3>Click to select image files<br>or just drop files here</h3> | |
<input type="file" id="image_fileInput" name="UploadForm[image]"> | |
</div> | |
</label> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* IMAGE UPLOAD CODE | |
* ============================================= */ | |
/** | |
* dragenter event handler | |
* @param event {object} | |
*/ | |
var containerDragenter = function (event) { | |
if (event.target === $scope.container) { | |
angular.element($scope.dropzone).addClass('dragstarted'); | |
} | |
}; | |
/** | |
* dragleave event handler | |
* @param event | |
*/ | |
var containerDragleave = function (event) { | |
if (event.target === $scope.container) { | |
angular.element($scope.dropzone).removeClass('dragstarted'); | |
} | |
}; | |
/** | |
* event listener fired on files selected/dropped | |
* @param event {object} | |
*/ | |
$scope.images = []; | |
var images = $scope.images; | |
var handleDrop = function (event) { | |
event.stopPropagation(); | |
var files = event.target.files; | |
angular.element($scope.dropzone).addClass("processing"); | |
// handle the last one file | |
var i = files.length - 1; | |
//init empty object (status: new, uploading, error, done ) | |
images.push({ file: files[i], status: 'new', percentage: 0, fieldIndex: $scope.activeFieldIndex }); | |
// iterate over file(s) and process them for uploading | |
uploadFile(images.length - 1); | |
angular.element($scope.dropzone).removeClass("processing"); | |
}; | |
/** | |
* helper function to create new instance of FileReader | |
*/ | |
$scope.createFileReader = function () { | |
return new FileReader(); | |
}; | |
//upload events listeners | |
var uploadProgress = function (event, fileIndex) { | |
$scope.$apply(function () { | |
var image = images[fileIndex]; | |
image.status = 'uploading'; | |
image.percentage = Math.round((event.loaded / event.total) * 100); | |
}); | |
}; | |
var uploadError = function (event, fileIndex) { | |
$scope.$apply(function () { | |
images[fileIndex].status = 'error'; | |
}); | |
}; | |
var uploadAbort = function (event, fileIndex) { | |
// | |
}; | |
var uploadComplete = function (event, fileIndex) { | |
$scope.$apply(function () { | |
var image = images[fileIndex]; | |
if (image.status !== 'error') { | |
image.percentage = 100; | |
image.status = 'done'; | |
} | |
}); | |
}; | |
/** | |
* performs file upload to api | |
* @param fileIndex {int} index of file object in images array | |
*/ | |
var uploadFile = function (fileIndex) { | |
var image = images[fileIndex], | |
fd = new FormData(); | |
//fd.append('file', image.file);//upload original file | |
fd.append('image', image.file); | |
image.xhr = new XMLHttpRequest(); | |
//register upload progress event listener | |
image.xhr.upload.addEventListener("progress", function (event) { | |
uploadProgress(event, fileIndex); | |
}, false); | |
image.xhr.addEventListener("load", function (event) { | |
uploadComplete(event, fileIndex); | |
}, false); | |
image.xhr.addEventListener("error", function (event) { | |
uploadError(event, fileIndex); | |
}, false); | |
image.xhr.addEventListener("abort", function (event) { | |
uploadAbort(event, fileIndex); | |
}, false); | |
image.xhr.onload = function (event) { | |
if (this.status == 200) { | |
//image successfully uploaded - populate object with received data | |
var apiResponse = JSON.parse(this.responseText); | |
$scope.$apply(function () { | |
var image = images[fileIndex]; | |
image.url = apiResponse.response.image; | |
$scope.form.fields[image.fieldIndex].value = image.url; | |
if (apiResponse.response.width > 800) { | |
var proportion = 800 / apiResponse.response.width; | |
apiResponse.response.width = 800; | |
apiResponse.response.height = Math.ceil(proportion * apiResponse.response.height); | |
} | |
// update image dimentions with actual | |
$scope.form.fields[image.fieldIndex].settings.width = apiResponse.response.width; | |
$scope.form.fields[image.fieldIndex].settings.height = apiResponse.response.height; | |
}); | |
} else { | |
//some error occurred | |
apiResponse = JSON.parse(this.responseText); | |
if (apiResponse.status === false) { | |
$scope.$apply(function () { | |
image = images[fileIndex]; | |
image.status = 'error'; | |
}); | |
} | |
} | |
}; | |
//send file to server | |
image.xhr.open("POST", '/location/' + $scope.form.location_id + '/manage/uploadImage'); | |
image.xhr.send(fd); | |
}; | |
// init html elements event listeners | |
var ctrlPrefix = 'image_'; | |
if (!$scope.dropzone) { | |
$scope.dropzone = document.getElementById(ctrlPrefix + 'dropzone'); | |
} | |
if (!$scope.fileInput) { | |
$scope.fileInput = document.getElementById(ctrlPrefix + 'fileInput'); | |
} | |
if (!$scope.container) { | |
$scope.container = document.getElementById(ctrlPrefix + 'container'); | |
} | |
if (!$scope.container) { | |
throw 'Error: no container element found (#' + ctrlPrefix + 'container)'; | |
} | |
if (!$scope.fileInput) { | |
throw 'Error: no input[type="file"] found (#' + ctrlPrefix + 'fileInput)'; | |
} | |
$scope.fileInput.addEventListener("change", handleDrop, false); | |
$scope.container.addEventListener('dragenter', containerDragenter, true); | |
$scope.container.addEventListener('dragleave', containerDragleave, true); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment