Closed bettysteger closed 10 years ago
Hi. Thanks.
allow upload of blob
Blob uploading is possible. You can pass any data with file. Probably, in your case it looks like this:
// client
uploader.onAfterAddingFile = function(item) {
item.formData.push({name: item.file.name});
};
// server
$name = $_POST['name'];
what do you think of adding a third parameter or allow to upload a Blob in the first place?
I can write something like this
form.append(item.alias, item._file, item.file.name);
insted that code. What do you think about it?
Yes @nervgh, changing this line of code is what I meant ;) because then I don't need to add additional formData (client) and I don't need to get the name extra on the server, because it would work out of the box (with carrierwave)
Blob uploading is possible. You can pass any data with file.
yes, I know that, but I don't want it to pass it with the file, I want to just upload a Blob... that's why I overwrite item._file before the upload ;)
Thanks =)
@lpsBetty @nervgh Do any of you have a functional example of using ngImgCrop together with this uploader? I just can't make it work.
hey @TrkiSF2, I used onBeforeUploadItem to overwrite the actual '_file' with the blob:
updated solution, if you have a scope inheritance problem: https://gist.github.com/lpsBetty/2057e0bd0b4142d4070db0e1175ca47e
/**
* Show preview with cropping
*/
uploader.onAfterAddingFile = function(item) {
$scope.croppedImage = '';
var reader = new FileReader();
reader.onload = function(event) {
$scope.$apply(function(){
$scope.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($scope.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});
};
and the HTML:
<!-- crop area if uploaded image-->
<img-crop ng-show="image" image="image" result-image="croppedImage" area-type="square" result-image-size="250"></img-crop>
I hope I can you help you with that snippets ;)
IpsBetty thank you for the code! I will try it when I come home but from a quick view I am missing one thing. When do you call something like $scope.uploader.addToQueue(item) and how the item object looks like in that state please?
the uploader is bind to the dropzone and to the input field in my HTML.
so when a file is chosen uploader.onAfterAddingFile
(see above) will be called
Thank you very much. I made it work finally!!! :) If you would like to stay in touch https://twitter.com/TrkiSF2
@lpsBetty , thanks =)
Sorry to continue this thread that's already long - @TrkiSF2, any chance you could post your working code as a Plunkr or similar?
@lpsBetty - thank you SO much for posting your code. I'm just curious what the HTML context is for the upload directory? I realize that we're saving the base64 encoded image string to $scope.image
. But the reference to that via your example (<img-crop image="image">
) doesn't seem to be working. If I simply do <img ng-src="{{image}}">
then the data URI correctly renders an image, but passing $scope.image
has no effect when used in the context of the <img-crop>
directive from your example. Any ideas? This is such a WONDERFUL use case, would be great to include in the docs, since client side crop is an amazing complement to this directive.
Maybe someone can share what wraps the example crop code from here:
<!-- crop area if uploaded image-->
<img-crop ng-show="image" image="image" result-image="croppedImage" area-type="square" result-image-size="250"></img-crop>
@nervgh - I spent days recreating this functionality in raw javascript, and got it working. However, this directive is so well written and documented I'm definitely tossing that work in favor of this library. Great documentation, robust eventing, and modular / flexible - Thank you!!!
Ugh, sorry for the stupid question (though I think the full HTML template would still be great to post). Turns out I was just missing the CSS which is required for the ngImgCrop
directive
.cropArea {
background: #E4E4E4;
overflow: hidden;
width:500px;
height:350px;
}
Thanks again @lpsBetty! I had to make some changes to accomodate multi-file uploads, I think your code was assuming singular. For anyone else that wants to see all the moving parts, I've created a public gist that wires it all together:
@brianfeister yes i just needed single file upload, thanks your gist :+1:
Hi @nervgh Is there any way to trigger upload image event? Actually i want to upload the image after inserting/updating the data?
Hi @chin2, there is a property called autoUpload
, see https://github.com/nervgh/angular-file-upload/wiki/Module-API
just set it to true
Thanks @lpsBetty :+1:
Hi, @lpsBetty, @nervgh Yes one thing is that i want to load a default image while rendering the FileUpload, is it possible?
@chin2 So you want an image already in the queue? why do you want that?
@lpsBetty Actually while edit form, the uploaded image should be rendered. Have you got idea what is want exactly?
@chin2 so you want a preview? just use the result-image
like this:
<!-- crop area if uploaded image-->
<img-crop ng-show="image" image="image" result-image="croppedImage" area-type="square" result-image-size="150"></img-crop>
<!-- preview -->
<img alt="avatar_preview" ng-src="{{croppedImage}}" width="150" height="150" />
angular-file-upload how to add an parameter in url? /* the 'sn' is i want to add it in the url/ var uploader = $scope.uploader = new FileUploader({ url:url+'/ver/1.0/members/~/orgs/~/vas/'+sn+'/photo' , autoUpload: false, headers:{'Authorization':accessKey+':0a632a6beaf24928b1ccfdf7bc680317','Accept':'/*'} }); uploader.onSuccessItem = function(fileItem, response, status, headers) { if(response.retCode == "SUCCESS"){ $scope.vasPhoto = response.data.path; }else{ alert(response.msg); } };
TH's @lpsBetty
Hi, @lpsBetty is it possible to upload both original image and the cropped image?
@hfar hmmm maybe with two end points?
Hi, I want to use this uploader for uploading multiple files, I am able to do that, now new thing is when it comes to mobile I should be able to click picture & upload that, I think there is no direct way, so I used following for picture :
</div>
I see the image on click of button & camera, but how to upload it now thro.' this uploader ?
div class="visible-sm visible-xs form-group">input type="file" accept="image/*" id="capture" capture="camera">/div>
Above is the code I used, appreciate your help.
@kkmoghe I think it should work automatically? What is your actual HTML ? you can use ```` to write code in github
<div class="visible-sm visible-xs form-group">
<input type="file" accept="image/*" id="captureImage" capture="camera" nv-file-select="" uploader="uploader" onchange="angular.element($('captureImage')).scope().$apply(function($scope){$scope.uploader.changeFile();});">
</div>
Above is the code.
@kkmoghe ok this is definitely the wrong thread for your question! why do you use the onchange
attribute.. there is no need for that!
First: what is your controller code? Hopefully you define $scope.uploader
?
Second: what do you want to do? When you select an image immediately upload? Then here is the solution in your controller, just add:
$scope.uploader.autoUpload = true;
Hi Bettina, Sorry to post it in wrong thread, but your help is much appreciated.Sorry to post it in wrong thread, but your help is much appreciated.
yes I have $scope.uploader My requirement is not to immediately upload, I should be able to upload multi-files in desktop as well as mobile, so for desktop it works : I am pasting my uploader declaration & my tpl code to use that. So desktop it works, but for photo, I used that capture tag, but some how it is ignoring it, in mobile I am displaying two buttons one for capture=camera and other like normal desktop, camera is clicking & I see the file name after that, but its not getting uploaded, so I think I am missing some thing, where it is going wrong ?
uploader is defined in controller as :
var uploader = $scope.uploader = new FileUploader({
sendAllAtOnceItemsMultipleFileInputs: false,
url: '',
dataType: "json",
cache: false,
contentType: "application/json",
aliases: 'file1,file2,file3,file4,file5,file6'
});
<div class="pr">
<div class="form-group">
<div class="visible-sm visible-xs form-group">
<input type="file" accept="image/*" id="captureImage" capture="camera" nv-file-select="" uploader="uploader" onchange="angular.element($('captureImage')).scope().$apply(function($scope){$scope.uploader.changeFile();});">
</div>
<div id="ChooseBtnLabel" class="uploadfix" ng-show="checkNoOfAttachedFiles()">Select a File
<input type="file" nv-file-select="" class="multi"
uploader="uploader"
onchange="angular.element($('#ChooseBtnLabel')).scope().$apply(function($scope){$scope.uploader.changeFile();});"
multiple />
</div>
<p ng-show="invalidAddFileAttemptMessage!==''" class="red">{{invalidAddFileAttemptMessage}}</p>
<div class="MultiFile-list" id="files_wrap_list"
ng-repeat="item in uploader.queue">
<div ng-if="uploader.isUploading">Uploading...
</div>
<div ng-hide="'NO_FILES_CHOSEN' === item.file.name">
<a class="MultiFile-remove" ng-click="removeItemFromQueue(item);">x</a>
<span class="MultiFile-label MultiFile-title" ng-bind="item.file.name"></span>
</div>
</div>
</div>
</div>
</div>
sorry I don't know why!
@kkmoghe I don't use capture.. but maybe you should use another file uploader.. I saw that https://github.com/danialfarid/ng-file-upload supports capture!
ok, thx. I got this uploader in my search, but nervgh uploader we are using in our existing other modules also, so my design team is reluctant to add this another uploader just for mobile photo capture, they suggest me to use nervgh or write your own plugin.
@lpsBetty, folowed your code but I'm getting null value in myCroppedImage on uploader.onBeforeUploadItem function. Coudn't convert to blod value. Please Check my following code
$scope.myImage=''; $scope.myCroppedImage='';
uploader.onAfterAddingFile = function(item) {
var reader = new FileReader();
reader.onload = function(event) {
$scope.$apply(function(){
$scope.myImage = event.target.result;
});
};
reader.readAsDataURL(item._file);
};
uploader.onBeforeUploadItem = function(item) {
var blob = dataURItoBlob($scope.myCroppedImage);
console.log(blob);
item._file = 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});
};
Please help me on this
$scope.croppedImage is Undefined cant get blob data
what am i missing? need help please
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}); };
$scope.handleFileSelect = function (evt) {
var file = evt.currentTarget.files[0];
$scope.$apply(function ($scope) {
$scope.myImage = URL.createObjectURL(file);
});
};
var handleFileSelect=function(evt) {
$scope.croppedImage = '';
$scope.myImage = '';
var file=evt.currentTarget.files[0];
var reader = new FileReader();
reader.onload = function (evt) {
$scope.$apply(function($scope){
$scope.myImage=evt.target.result;
});
};
reader.readAsDataURL(file);
console.log($scope.croppedImage);
};
angular.element(document.querySelector('#fileInput')).on('change',handleFileSelect);
var uploader = $scope.uploader = new FileUploader({
url: '/upload.php'
});
// FILTERS
uploader.filters.push({
name: 'customFilter',
fn: function(item /*{File|FileLikeObject}*/, options) {
return this.queue.length < 10;
}
});
// CALLBACKS
uploader.onWhenAddingFileFailed = function(item /*{File|FileLikeObject}*/, filter, options) {
console.info('onWhenAddingFileFailed', item, filter, options);
};
uploader.onAfterAddingFile = function(fileItem) {
};
uploader.onAfterAddingAll = function(addedFileItems) {
console.info('onAfterAddingAll', addedFileItems);
};
uploader.onBeforeUploadItem = function(item) {
console.log('=================');
console.log($scope.croppedImage);
var blob = dataURItoBlob($scope.croppedImage);
item._file = blob;
};
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);
hmmm I really don't know what's the problem, but it could be a 'scope' inheritance problem, because of this I changed my cropped image model to an object to make sure that it set by the ngImgCrop!
from croppedImage
to cropped = {image: ''}
Here is the full code:
/**
* Show preview of cropped image
*/
uploader.onAfterAddingFile = function(item) {
$scope.cropped = {image: ''};
var reader = new FileReader();
reader.onload = function(event) {
$scope.$apply(function(){
$scope.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($scope.cropped.image);
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) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0) {
byteString = atob(dataURI.split(',')[1]);
} else {
byteString = decodeURI(dataURI.split(',')[1]);
}
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
var array = [];
for(var i = 0; i < byteString.length; i++) {
array.push(byteString.charCodeAt(i));
}
return new Blob([new Uint8Array(array)], {type: mimeString});
};
@lpsBetty Could you please tell me how to trigger the upload onAfterAddingFile function. Currebtly im using this, $(document).on('change', '#fileInput', function(event) { uploader.onAfterAddingFile(event); });
But it is not working as it is.
@madhurangaonbit you don't need this JS, you can just add this line and the uploader will automatically upload the image:
uploader.autoUpload = true;
see https://github.com/nervgh/angular-file-upload/wiki/Module-API
the callback function of onAfterAddingFile
will be called everytime a file is added in the browser..
im sorry for no response i have something to do on my work so.. btw thank you so much i got it work using your approach thank you so much :)
madhurangaonbit
FileUploader.FileSelect.prototype.isEmptyAfterSelection = function() {
return false;
};
@lpsBetty , thank you very much for your solution, finally solved my issue, I have struggled on that for several days.
Hi @lpsBetty ,
On my IOS mobile application I am taking picture and then select a picture from gallery. After selecting this picture I am using ng-img-crop.js to crop this image and without saving this cropped image, trying to upload it to a server. (In this partivular example I am trying to upload local IIS)
I am using local IIS 7.5 and installed asp, isapi etc. Now I am getting 0 from the response. Image is not uploaded to the server and there is no error log on IIS. Would you please help me?
Best Regards.
Here is my sample js: `angular.module('starter', ['ionic', 'ngCordova', 'ngImgCrop', 'ngFileUpload'])
.controller("ExampleController", ['$scope', '$cordovaCamera', 'Upload', '$timeout', '$cordovaFileTransfer', function ($scope, $cordovaCamera, Upload, $timeout, $cordovaFileTransfer) {
$scope.takePhoto = function () {
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.CAMERA,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: true
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.imgURI = "data:image/jpeg;base64," + imageData;
}, function (err) {
console.log(err);
alert(err);
});
}
$scope.choosePhoto = function () {
var options = {
quality: 100,
destinationType: Camera.DestinationType.DATA_URL,
sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
allowEdit: true,
encodingType: Camera.EncodingType.JPEG,
targetWidth: 300,
targetHeight: 300,
popoverOptions: CameraPopoverOptions,
saveToPhotoAlbum: false
};
$cordovaCamera.getPicture(options).then(function (imageData) {
$scope.imgURI = "data:image/jpeg;base64," + imageData;
$scope.myImage = $scope.imgURI;
}, function (err) {
console.log(err);
alert(err);
});
}
$scope.myCroppedImage = '';
$scope.upload = function (dataUrl) {
Upload.upload({
url: 'http://192.168.1.20/wcf/upload',
data: {
file: Upload.dataUrltoBlob(dataUrl)
},
}).then(function (response) {
$timeout(function () {
$scope.result = response.data;
console.log(response.data);
alert(response.data);
});
console.log(response.data);
}, function (response) {
if (response.status > 0) $scope.errorMsg = response.status
+ ': ' + response.data;
alert(response.status);
});
}
}]);`
And here is the related markup: `
<img-crop image="myImage" result-image="myCroppedImage" chargement="'Loading'"
area-type="rectangle"
area-min-size="50"
result-image-format="image/jpeg"
result-image-quality="1"
result-image-size="{w:300, h:50}"></img-crop>
</div>
<div ng-show="myImage !== undefined">Gönderilecek Resim:</div>
<div class="croppedArea"><img ng-src="{{myCroppedImage}}" ng-show="myImage !== undefined" id="image" /></div>
</center>
<button class="button button-full button-balanced icon-right ion-images" ng-click="upload(myCroppedImage);" ng-if="myImage !== undefined">
Resim Yükle
</button>`
@raysefo what is IIS ? ;)
@lpsBetty Internet Information Services (IIS) for Windows for my local PC :) Should I use file transfer plugin (https://www.npmjs.com/package/cordova-plugin-file-transfer) instead?
any idea @lpsBetty ?
hmm @raysefo no sorry, I have no experience with IIS..
Lets forget about IIS, as a result it is a server. What is the difference between file upload and file transfer? @lpsBetty
@lpsBetty @nervgh can we have
formData = new FormData();
formData.append("categoryCode", $scope.category.name);
formData.append("request",item._file);
$http.post(URL,formData);
and this works great for me when i pass it to java spring backend but the problem is it won't update item.progress property . any solution?
@MrSpark2591 yeah that is because you are not using the fileuploader for uploading the actual image, you are just making your own POST request - if you use fileuploader with the correct functions (uploadAll
or uploadItem
) it works!
hey I just used https://github.com/alexk111/ngImgCrop to crop an image before uploading.. and now I did this to upload the blob with angular-file-upload:
This works just fine, but the file name is ignored because of this line: (and because of that the server doesn't recognize the file extension)
It would be possible to add the name as third parameter, see https://developer.mozilla.org/en-US/docs/Web/API/FormData
what do you think of adding a third parameter or allow to upload a Blob in the first place?
btw: you made a really cool plugin!