Last active
May 27, 2020 02:37
-
-
Save brianfeister/56a1c6c77cd5928a1c53 to your computer and use it in GitHub Desktop.
Angular Upload with Image Crop
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
angular.module('cropAndUpload', [ | |
'angularFileUpload', | |
'ngImgCrop' | |
]) |
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
angular.module('cropAndUpload') | |
.controller('Ctrl', function ($scope, FileUploader) { | |
var uploader = $scope.uploader = new FileUploader({ | |
url: '/api/users/photo' | |
}); | |
// FILTERS | |
uploader.filters.push({ | |
name: 'imageFilter', | |
fn: function(item /*{File|FileLikeObject}*/, options) { | |
var type = '|' + item.type.slice(item.type.lastIndexOf('/') + 1) + '|'; | |
return '|jpg|png|jpeg|bmp|gif|'.indexOf(type) !== -1; | |
} | |
}); | |
// CALLBACKS | |
/** | |
* Show preview with cropping | |
*/ | |
uploader.onAfterAddingFile = function(item) { | |
// $scope.croppedImage = ''; | |
item.croppedImage = ''; | |
var reader = new FileReader(); | |
reader.onload = function(event) { | |
$scope.$apply(function(){ | |
item.image = event.target.result; | |
}); | |
}; | |
reader.readAsDataURL(item._file); | |
}; | |
/** | |
* Upload Blob (cropped image) instead of file. | |
* @see | |
* https://developer.mozilla.org/en-US/docs/Web/API/FormData | |
* https://github.com/nervgh/angular-file-upload/issues/208 | |
*/ | |
uploader.onBeforeUploadItem = function(item) { | |
var blob = dataURItoBlob(item.croppedImage); | |
item._file = blob; | |
}; | |
/** | |
* Converts data uri to Blob. Necessary for uploading. | |
* @see | |
* http://stackoverflow.com/questions/4998908/convert-data-uri-to-file-then-append-to-formdata | |
* @param {String} dataURI | |
* @return {Blob} | |
*/ | |
var dataURItoBlob = function(dataURI) { | |
var binary = atob(dataURI.split(',')[1]); | |
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]; | |
var array = []; | |
for(var i = 0; i < binary.length; i++) { | |
array.push(binary.charCodeAt(i)); | |
} | |
return new Blob([new Uint8Array(array)], {type: mimeString}); | |
}; | |
uploader.onWhenAddingFileFailed = function(item /*{File|FileLikeObject}*/, filter, options) { | |
console.info('onWhenAddingFileFailed', item, filter, options); | |
}; | |
uploader.onAfterAddingAll = function(addedFileItems) { | |
console.info('onAfterAddingAll', addedFileItems); | |
}; | |
uploader.onProgressItem = function(fileItem, progress) { | |
console.info('onProgressItem', fileItem, progress); | |
}; | |
uploader.onProgressAll = function(progress) { | |
console.info('onProgressAll', progress); | |
}; | |
uploader.onSuccessItem = function(fileItem, response, status, headers) { | |
console.info('onSuccessItem', fileItem, response, status, headers); | |
}; | |
uploader.onErrorItem = function(fileItem, response, status, headers) { | |
console.info('onErrorItem', fileItem, response, status, headers); | |
}; | |
uploader.onCancelItem = function(fileItem, response, status, headers) { | |
console.info('onCancelItem', fileItem, response, status, headers); | |
}; | |
uploader.onCompleteItem = function(fileItem, response, status, headers) { | |
console.info('onCompleteItem', fileItem, response, status, headers); | |
}; | |
uploader.onCompleteAll = function() { | |
console.info('onCompleteAll'); | |
}; | |
console.info('uploader', uploader); | |
}); |
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
<div class="container" ng-controller="Ctrl"> | |
<div class="row"> | |
<div class="col-sm-12"> | |
<div class="row" nv-file-drop="" uploader="uploader"> | |
<div class="col-md-3"> | |
<h3>Select files</h3> | |
<div ng-show="uploader.isHTML5"> | |
<!-- 3. nv-file-over uploader="link" over-class="className" --> | |
<div class="well my-drop-zone" nv-file-over="" uploader="uploader"> | |
Base drop zone | |
</div> | |
<!-- Example: nv-file-drop="" uploader="{Object}" options="{Object}" filters="{String}" --> | |
<div nv-file-drop="" uploader="uploader" options="{ url: '/foo' }"> | |
<div nv-file-over="" uploader="uploader" over-class="another-file-over-class" class="well my-drop-zone"> | |
Another drop zone with its own settings | |
</div> | |
</div> | |
</div> | |
<!-- Example: nv-file-select="" uploader="{Object}" options="{Object}" filters="{String}" --> | |
<input type="file" nv-file-select="" uploader="uploader" multiple /><br/> | |
</div> | |
<div class="col-md-9" style="margin-bottom: 40px"> | |
<h2>Uploads only images (with canvas preview)</h2> | |
<h3>The queue</h3> | |
<p>Queue length: {{ uploader.queue.length }}</p> | |
<table class="table"> | |
<thead> | |
<tr> | |
<th width="50%">Name</th> | |
<th ng-show="uploader.isHTML5">Size</th> | |
<th ng-show="uploader.isHTML5">Progress</th> | |
<th>Status</th> | |
<th>Actions</th> | |
</tr> | |
</thead> | |
<tbody> | |
<tr ng-repeat="item in uploader.queue"> | |
<td> | |
<strong>{{ item.file.name }}</strong> | |
<div class="cropArea"> | |
<img-crop image="item.image" result-image="item.croppedImage"></img-crop> | |
</div> | |
<div>Cropped Image:</div> | |
<div><img ng-src="{{item.croppedImage}}" /></div> | |
</td> | |
<td ng-show="uploader.isHTML5" nowrap>{{ item.file.size/1024/1024|number:2 }} MB</td> | |
<td ng-show="uploader.isHTML5"> | |
<div class="progress" style="margin-bottom: 0;"> | |
<div class="progress-bar" role="progressbar" ng-style="{ 'width': item.progress + '%' }"></div> | |
</div> | |
</td> | |
<td class="text-center"> | |
<span ng-show="item.isSuccess"><i class="glyphicon glyphicon-ok"></i></span> | |
<span ng-show="item.isCancel"><i class="glyphicon glyphicon-ban-circle"></i></span> | |
<span ng-show="item.isError"><i class="glyphicon glyphicon-remove"></i></span> | |
</td> | |
<td nowrap> | |
<button type="button" class="btn btn-success btn-xs" ng-click="item.upload()" ng-disabled="item.isReady || item.isUploading || item.isSuccess"> | |
<span class="glyphicon glyphicon-upload"></span> Upload | |
</button> | |
<button type="button" class="btn btn-warning btn-xs" ng-click="item.cancel()" ng-disabled="!item.isUploading"> | |
<span class="glyphicon glyphicon-ban-circle"></span> Cancel | |
</button> | |
<button type="button" class="btn btn-danger btn-xs" ng-click="item.remove()"> | |
<span class="glyphicon glyphicon-trash"></span> Remove | |
</button> | |
</td> | |
</tr> | |
</tbody> | |
</table> | |
<div> | |
<div> | |
Queue progress: | |
<div class="progress" style=""> | |
<div class="progress-bar" role="progressbar" ng-style="{ 'width': uploader.progress + '%' }"></div> | |
</div> | |
</div> | |
<button type="button" class="btn btn-success btn-s" ng-click="uploader.uploadAll()" ng-disabled="!uploader.getNotUploadedItems().length"> | |
<span class="glyphicon glyphicon-upload"></span> Upload all | |
</button> | |
<button type="button" class="btn btn-warning btn-s" ng-click="uploader.cancelAll()" ng-disabled="!uploader.isUploading"> | |
<span class="glyphicon glyphicon-ban-circle"></span> Cancel all | |
</button> | |
<button type="button" class="btn btn-danger btn-s" ng-click="uploader.clearQueue()" ng-disabled="!uploader.queue.length"> | |
<span class="glyphicon glyphicon-trash"></span> Remove all | |
</button> | |
</div> | |
</div> | |
</div> | |
</div> | |
</div> |
Thanks! Exactly what I was looking for :)
Exactly what I need 💯
Thanks a Lot !!!
Great!
Did the progress bar work for you?
Solved 💃 Just need to add bootstrap libs!
Thank you!
You can try using uiCropper, a fork of imgCrop - https://github.com/CrackerakiUA/ui-cropper - which can already output blobs. No need to manually convert to blob first. It works great for me.
@rhclayto, can You show snippet of your Code, with usage ui-cropper with this plugin?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Here is codepen and PHP back end code
http://codepen.io/muralidharm/pen/gMmJPN