move a file from the client-side to the server - javascript

I have an html upload form and an angular controller controlling it. In the controller, I found out how to get the files uploaded but my question is how can I move/upload these files to the server? I checked out multer but I don't believe this is going to work in my case because I can't require it in the client-side. Here is what my controller currently looks like:
app.controller('uploadCtrl', function($scope, $location, $http){
$scope.enableSubmitButton = false;
$scope.fileSizeError = false;
var selectedFiles = [];
//get files selected
$scope.getFiles = function($files){
selectedFiles = $files;
//display upload button if there is a valid file to upload
if(selectedFiles.length !== 0){
$scope.enableSubmitButton = true;
}
}
$scope.upload = function(){
if($scope.enableSubmitButton){
//disable to prevent clicking again
$scope.enableSubmitButton = false;
//correctly shows the file data
console.dir(selectedFiles);
//upload files to server
//What should I do here?
}
}
});

Here is an example
Step:1 Initialize Your app
var myApp = angular.module('myApp', []);
Step:2 Make a directive named fileModel. it can use link funtion and bind change property so that if a file upload, change function executes
and then set model scope with files object.simple it parses file object
myApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A', //define attribute
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
Step:3 Make a fileUpload service so that transfer file to server using $http
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData(); //FormData
fd.append('file', file); //file object
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined} //define req headers
})
.success(function(){
})
.error(function(){
});
}
}]);
Step:4 use fileUpload service and call its uploadFileToUrl function and pass file object and url for
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){ //uploadFile function
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);

Related

upload form with other form fiels angularjs [duplicate]

Here is my HTML form:
<form name="myForm" ng-submit="">
<input ng-model='file' type="file"/>
<input type="submit" value='Submit'/>
</form>
I want to upload an image from local machine and want to read the content of the uploaded file. All this I want to do using AngularJS.
When I try to print the value of $scope.file it comes as undefined.
Some of the answers here propose using FormData(), but unfortunately that is a browser object not available in Internet Explorer 9 and below. If you need to support those older browsers, you will need a backup strategy such as using <iframe> or Flash.
There are already many Angular.js modules to perform file uploading. These two have explicit support for older browsers:
https://github.com/leon/angular-upload - uses iframes as a fallback
https://github.com/danialfarid/ng-file-upload - uses FileAPI/Flash as a fallback
And some other options:
https://github.com/nervgh/angular-file-upload/
https://github.com/uor/angular-file
https://github.com/twilson63/ngUpload
https://github.com/uploadcare/angular-uploadcare
One of these should fit your project, or may give you some insight into how to code it yourself.
The easiest is to use HTML5 API, namely FileReader
HTML is pretty straightforward:
<input type="file" id="file" name="file"/>
<button ng-click="add()">Add</button>
In your controller define 'add' method:
$scope.add = function() {
var f = document.getElementById('file').files[0],
r = new FileReader();
r.onloadend = function(e) {
var data = e.target.result;
//send your binary data via $http or $resource or do anything else with it
}
r.readAsBinaryString(f);
}
Browser Compatibility
Desktop Browsers
Edge 12, Firefox(Gecko) 3.6(1.9.2),
Chrome 7, Opera* 12.02, Safari 6.0.2
Mobile Browsers
Firefox(Gecko) 32,
Chrome 3,
Opera* 11.5,
Safari 6.1
Note : readAsBinaryString() method is deprecated and readAsArrayBuffer() should be used instead.
This is the modern browser way, without 3rd party libraries. Works on all the latest browsers.
app.directive('myDirective', function (httpPostFactory) {
return {
restrict: 'A',
scope: true,
link: function (scope, element, attr) {
element.bind('change', function () {
var formData = new FormData();
formData.append('file', element[0].files[0]);
httpPostFactory('upload_image.php', formData, function (callback) {
// recieve image name to use in a ng-src
console.log(callback);
});
});
}
};
});
app.factory('httpPostFactory', function ($http) {
return function (file, data, callback) {
$http({
url: file,
method: "POST",
data: data,
headers: {'Content-Type': undefined}
}).success(function (response) {
callback(response);
});
};
});
HTML:
<input data-my-Directive type="file" name="file">
PHP:
if (isset($_FILES['file']) && $_FILES['file']['error'] == 0) {
// uploads image in the folder images
$temp = explode(".", $_FILES["file"]["name"]);
$newfilename = substr(md5(time()), 0, 10) . '.' . end($temp);
move_uploaded_file($_FILES['file']['tmp_name'], 'images/' . $newfilename);
// give callback to your angular code with the image src name
echo json_encode($newfilename);
}
js fiddle (only front-end)
https://jsfiddle.net/vince123/8d18tsey/31/
Below is working example of file upload:
http://jsfiddle.net/vishalvasani/4hqVu/
In this one function called
setFiles
From View which will update the file array in controller
or
You can check jQuery File Upload using AngularJS
http://blueimp.github.io/jQuery-File-Upload/angularjs.html
You can achieve nice file and folder upload using flow.js.
https://github.com/flowjs/ng-flow
Check out a demo here
http://flowjs.github.io/ng-flow/
It doesn't support IE7, IE8, IE9, so you'll eventually have to use a compatibility layer
https://github.com/flowjs/fusty-flow.js
Use the onchange event to pass the input file element to your function.
<input type="file" onchange="angular.element(this).scope().fileSelected(this)" />
So when a user selects a file, you have a reference to it without the user needing to click an "Add" or "Upload" button.
$scope.fileSelected = function (element) {
var myFileSelected = element.files[0];
};
I tried all alternatives that #Anoyz (Correct answer) gives... and the best solution is https://github.com/danialfarid/angular-file-upload
Some Features:
Progress
Multifiles
Fields
Old browsers (IE8-9)
It's work fine for me. You just have to pay attention to instructions.
In server-side i use NodeJs, Express 4 and Multer middleware to manage multipart request.
HTML
<html>
<head></head>
<body ng-app = "myApp">
<form ng-controller = "myCtrl">
<input type = "file" file-model="files" multiple/>
<button ng-click = "uploadFile()">upload me</button>
<li ng-repeat="file in files">{{file.name}}</li>
</form>
Scripts
<script src =
"http://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script>
angular.module('myApp', []).directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.bind('change', function(){
$parse(attrs.fileModel).assign(scope,element[0].files)
scope.$apply();
});
}
};
}]).controller('myCtrl', ['$scope', '$http', function($scope, $http){
$scope.uploadFile=function(){
var fd=new FormData();
console.log($scope.files);
angular.forEach($scope.files,function(file){
fd.append('file',file);
});
$http.post('http://localhost:1337/mediaobject/upload',fd,
{
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function(d)
{
console.log(d);
})
}
}]);
</script>
The <input type=file> element does not by default work with the ng-model directive. It needs a custom directive:
Working Demo of select-ng-files Directive that Works with ng-model1
angular.module("app",[]);
angular.module("app").directive("selectNgFiles", function() {
return {
require: "ngModel",
link: function postLink(scope,elem,attrs,ngModel) {
elem.on("change", function(e) {
var files = elem[0].files;
ngModel.$setViewValue(files);
})
}
}
});
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app">
<h1>AngularJS Input `type=file` Demo</h1>
<input type="file" select-ng-files ng-model="fileList" multiple>
<h2>Files</h2>
<div ng-repeat="file in fileList">
{{file.name}}
</div>
</body>
$http.post from a FileList
$scope.upload = function(url, fileList) {
var config = { headers: { 'Content-Type': undefined },
transformResponse: angular.identity
};
var promises = fileList.map(function(file) {
return $http.post(url, file, config);
});
return $q.all(promises);
};
When sending a POST with a File object, it is important to set 'Content-Type': undefined. The XHR send method will then detect the File object and automatically set the content type.
Easy with a directive
Html:
<input type="file" file-upload multiple/>
JS:
app.directive('fileUpload', function () {
return {
scope: true, //create a new scope
link: function (scope, el, attrs) {
el.bind('change', function (event) {
var files = event.target.files;
//iterate files since 'multiple' may be specified on the element
for (var i = 0;i<files.length;i++) {
//emit event upward
scope.$emit("fileSelected", { file: files[i] });
}
});
}
};
In the directive we ensure a new scope is created and then listen for changes made to the file input element. When changes are detected with emit an event to all ancestor scopes (upward) with the file object as a parameter.
In your controller:
$scope.files = [];
//listen for the file selected event
$scope.$on("fileSelected", function (event, args) {
$scope.$apply(function () {
//add the file object to the scope's files collection
$scope.files.push(args.file);
});
});
Then in your ajax call:
data: { model: $scope.model, files: $scope.files }
http://shazwazza.com/post/uploading-files-and-json-data-in-the-same-request-with-angular-js/
i think this is the angular file upload:
ng-file-upload
Lightweight Angular JS directive to upload files.
Here is the DEMO page.Features
Supports upload progress, cancel/abort upload while in progress, File drag and drop (html5), Directory drag and drop (webkit), CORS, PUT(html5)/POST methods, validation of file type and size, show preview of selected images/audio/videos.
Cross browser file upload and FileReader (HTML5 and non-HTML5) with Flash polyfill FileAPI. Allows client side validation/modification before uploading the file
Direct upload to db services CouchDB, imgur, etc... with file's content type using Upload.http(). This enables progress event for angular http POST/PUT requests.
Seperate shim file, FileAPI files are loaded on demand for non-HTML5 code meaning no extra load/code if you just need HTML5 support.
Lightweight using regular $http to upload (with shim for non-HTML5 browsers) so all angular $http features are available
https://github.com/danialfarid/ng-file-upload
Your file and json data uploading at the same time .
// FIRST SOLUTION
var _post = function (file, jsonData) {
$http({
url: your url,
method: "POST",
headers: { 'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
formData.append("model", angular.toJson(data.model));
formData.append("file", data.files);
return formData;
},
data: { model: jsonData, files: file }
}).then(function (response) {
;
});
}
// END OF FIRST SOLUTION
// SECOND SOLUTION
// If you can add plural file and If above code give an error.
// You can try following code
var _post = function (file, jsonData) {
$http({
url: your url,
method: "POST",
headers: { 'Content-Type': undefined },
transformRequest: function (data) {
var formData = new FormData();
formData.append("model", angular.toJson(data.model));
for (var i = 0; i < data.files.length; i++) {
// add each file to
// the form data and iteratively name them
formData.append("file" + i, data.files[i]);
}
return formData;
},
data: { model: jsonData, files: file }
}).then(function (response) {
;
});
}
// END OF SECOND SOLUTION
You can use a FormData object which is safe and fast:
// Store the file object when input field is changed
$scope.contentChanged = function(event){
if (!event.files.length)
return null;
$scope.content = new FormData();
$scope.content.append('fileUpload', event.files[0]);
$scope.$apply();
}
// Upload the file over HTTP
$scope.upload = function(){
$http({
method: 'POST',
url: '/remote/url',
headers: {'Content-Type': undefined },
data: $scope.content,
}).success(function(response) {
// Uploading complete
console.log('Request finished', response);
});
}
http://jsfiddle.net/vishalvasani/4hqVu/ works fine in chrome and IE (if you update CSS a little in background-image).
This is used for updating progress bar:
scope.progress = Math.round(evt.loaded * 100 / evt.total)
but in FireFox angular's [percent] data is not updated in DOM successfully,although files are uploading successfully.
You may consider IaaS for file upload, such as Uploadcare. There is an Angular package for it: https://github.com/uploadcare/angular-uploadcare
Technically it's implemented as a directive, providing different options for uploading, and manipulations for uploaded images within the widget:
<uploadcare-widget
ng-model="object.image.info.uuid"
data-public-key="YOURKEYHERE"
data-locale="en"
data-tabs="file url"
data-images-only="true"
data-path-value="true"
data-preview-step="true"
data-clearable="true"
data-multiple="false"
data-crop="400:200"
on-upload-complete="onUCUploadComplete(info)"
on-widget-ready="onUCWidgetReady(widget)"
value="{{ object.image.info.cdnUrl }}"
/>
More configuration options to play with: https://uploadcare.com/widget/configure/
I know this is a late entry but I have created a simple upload directive. Which you can get working in no time!
<input type="file" multiple ng-simple-upload web-api-url="/api/Upload" callback-fn="myCallback" />
ng-simple-upload more on Github with an example using Web API.
HTML
<input type="file" id="file" name='file' onchange="angular.element(this).scope().profileimage(this)" />
add 'profileimage()' method to your controller
$scope.profileimage = function(selectimage) {
console.log(selectimage.files[0]);
var selectfile=selectimage.files[0];
r = new FileReader();
r.onloadend = function (e) {
debugger;
var data = e.target.result;
}
r.readAsBinaryString(selectfile);
}
This should be an update/comment to #jquery-guru's answer but as I don't have enough rep it will go here. It fixes the errors that are now generated by the code.
https://jsfiddle.net/vzhrqotw/
The change is basically:
FileUploadCtrl.$inject = ['$scope']
function FileUploadCtrl(scope) {
To:
app.controller('FileUploadCtrl', function($scope)
{
Feel free to move to a more appropriate location if desired.
I've read all the thread and the HTML5 API solution looked the best. But it changes my binary files, corrupting them in a manner I've not investigated. The solution that worked perfectly for me was :
HTML :
<input type="file" id="msds" ng-model="msds" name="msds"/>
<button ng-click="msds_update()">
Upload
</button>
JS:
msds_update = function() {
var f = document.getElementById('msds').files[0],
r = new FileReader();
r.onloadend = function(e) {
var data = e.target.result;
console.log(data);
var fd = new FormData();
fd.append('file', data);
fd.append('file_name', f.name);
$http.post('server_handler.php', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
console.log('success');
})
.error(function(){
console.log('error');
});
};
r.readAsDataURL(f);
}
Server side (PHP):
$file_content = $_POST['file'];
$file_content = substr($file_content,
strlen('data:text/plain;base64,'));
$file_content = base64_decode($file_content);
I am able to upload files using AngularJS by using below code:
The file for the argument that needs to be passed for the function ngUploadFileUpload is $scope.file as per your question.
The key point here is to use transformRequest: []. This will prevent $http with messing with the contents of the file.
function getFileBuffer(file) {
var deferred = new $q.defer();
var reader = new FileReader();
reader.onloadend = function (e) {
deferred.resolve(e.target.result);
}
reader.onerror = function (e) {
deferred.reject(e.target.error);
}
reader.readAsArrayBuffer(file);
return deferred.promise;
}
function ngUploadFileUpload(endPointUrl, file) {
var deferred = new $q.defer();
getFileBuffer(file).then(function (arrayBuffer) {
$http({
method: 'POST',
url: endPointUrl,
headers: {
"accept": "application/json;odata=verbose",
'X-RequestDigest': spContext.securityValidation,
"content-length": arrayBuffer.byteLength
},
data: arrayBuffer,
transformRequest: []
}).then(function (data) {
deferred.resolve(data);
}, function (error) {
deferred.reject(error);
console.error("Error", error)
});
}, function (error) {
console.error("Error", error)
});
return deferred.promise;
}
Above accepted answer is not browser compatible. If some one has compatibility issue try this.
Fiddle
View Code
<div ng-controller="MyCtrl">
<input type="file" id="file" name="file"/>
<br>
<button ng-click="add()">Add</button>
<p>{{data}}</p>
</div>
Controller code
var myApp = angular.module('myApp',[]);
function MyCtrl($scope) {
$scope.data = 'none';
$scope.add = function(){
var f = document.getElementById('file').files[0],
r = new FileReader();
r.onloadend = function(e){
var binary = "";
var bytes = new Uint8Array(e.target.result);
var length = bytes.byteLength;
for (var i = 0; i < length; i++)
{
binary += String.fromCharCode(bytes[i]);
}
$scope.data = (binary).toString();
alert($scope.data);
}
r.readAsArrayBuffer(f);
}
}
in simple words
in Html - add below code only
<form name="upload" class="form" data-ng-submit="addFile()">
<input type="file" name="file" multiple
onchange="angular.element(this).scope().uploadedFile(this)" />
<button type="submit">Upload </button>
</form>
in the controller - This function is called when you click "upload file button". it will upload the file. you can console it.
$scope.uploadedFile = function(element) {
$scope.$apply(function($scope) {
$scope.files = element.files;
});
}
add more in controllers - below code add into the function . This function is called when you click on button which is used "hitting the api (POST)". it will send file(which uploaded) and form-data to the backend .
var url = httpURL + "/reporttojson"
var files=$scope.files;
for ( var i = 0; i < files.length; i++)
{
var fd = new FormData();
angular.forEach(files,function(file){
fd.append('file',file);
});
var data ={
msg : message,
sub : sub,
sendMail: sendMail,
selectUsersAcknowledge:false
};
fd.append("data", JSON.stringify(data));
$http.post(url, fd, {
withCredentials : false,
headers : {
'Content-Type' : undefined
},
transformRequest : angular.identity
}).success(function(data)
{
toastr.success("Notification sent successfully","",{timeOut: 2000});
$scope.removereport()
$timeout(function() {
location.reload();
}, 1000);
}).error(function(data)
{
toastr.success("Error in Sending Notification","",{timeOut: 2000});
$scope.removereport()
});
}
in this case .. i added below code as form data
var data ={
msg : message,
sub : sub,
sendMail: sendMail,
selectUsersAcknowledge:false
};
<form id="csv_file_form" ng-submit="submit_import_csv()" method="POST" enctype="multipart/form-data">
<input ng-model='file' type="file"/>
<input type="submit" value='Submit'/>
</form>
In angularJS controller
$scope.submit_import_csv = function(){
var formData = new FormData(document.getElementById("csv_file_form"));
console.log(formData);
$.ajax({
url: "import",
type: 'POST',
data: formData,
mimeType:"multipart/form-data",
contentType: false,
cache: false,
processData:false,
success: function(result, textStatus, jqXHR)
{
console.log(result);
}
});
return false;
}
We have used HTML, CSS and AngularJS. Following example shows about how to upload the file using AngularJS.
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body ng-app = "myApp">
<div ng-controller = "myCtrl">
<input type = "file" file-model = "myFile"/>
<button ng-click = "uploadFile()">upload me</button>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
myApp.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
myApp.controller('myCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload";
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
</script>
</body>
</html>
Working Example using Simple Directive (ng-file-model):
.directive("ngFileModel", [function () {
return {
$scope: {
ngFileModel: "="
},
link: function ($scope:any, element, attributes) {
element.bind("change", function (changeEvent:any) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
$scope.$apply(function () {
$scope.ngFileModel = {
lastModified: changeEvent.target.files[0].lastModified,
lastModifiedDate: changeEvent.target.files[0].lastModifiedDate,
name: changeEvent.target.files[0].name,
size: changeEvent.target.files[0].size,
type: changeEvent.target.files[0].type,
data: changeEvent.target.files[0]
};
});
}
reader.readAsDataURL(changeEvent.target.files[0]);
});
}
}
}])
and use FormData to upload file in your function.
var formData = new FormData();
formData.append("document", $scope.ngFileModel.data)
formData.append("user_id", $scope.userId)
all credits go for
https://github.com/mistralworks/ng-file-model
I have faced a small probelm you can check it here:
https://github.com/mistralworks/ng-file-model/issues/7
Finally,here's a forked repo: https://github.com/okasha93/ng-file-model/blob/patch-1/ng-file-model.js
The code will helps to insert file
<body ng-app = "myApp">
<form ng-controller="insert_Ctrl" method="post" action="" name="myForm" enctype="multipart/form-data" novalidate>
<div>
<p><input type="file" ng-model="myFile" class="form-control" onchange="angular.element(this).scope().uploadedFile(this)">
<span style="color:red" ng-show="(myForm.myFile.$error.required&&myForm.myFile.$touched)">Select Picture</span>
</p>
</div>
<div>
<input type="button" name="submit" ng-click="uploadFile()" class="btn-primary" ng-disabled="myForm.myFile.$invalid" value="insert">
</div>
</form>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<script src="insert.js"></script>
</body>
insert.js
var app = angular.module('myApp',[]);
app.service('uploadFile', ['$http','$window', function ($http,$window) {
this.uploadFiletoServer = function(file,uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(data){
alert("insert successfull");
$window.location.href = ' ';//your window location
})
.error(function(){
alert("Error");
});
}
}]);
app.controller('insert_Ctrl', ['$scope', 'uploadFile', function($scope, uploadFile){
$scope.uploadFile = function() {
$scope.myFile = $scope.files[0];
var file = $scope.myFile;
var url = "save_data.php";
uploadFile.uploadFiletoServer(file,url);
};
$scope.uploadedFile = function(element) {
var reader = new FileReader();
reader.onload = function(event) {
$scope.$apply(function($scope) {
$scope.files = element.files;
$scope.src = event.target.result
});
}
reader.readAsDataURL(element.files[0]);
}
}]);
save_data.php
<?php
require "dbconnection.php";
$ext = pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION);
$image = time().'.'.$ext;
move_uploaded_file($_FILES["file"]["tmp_name"],"upload/".$image);
$query="insert into test_table values ('null','$image')";
mysqli_query($con,$query);
?>
this works
file.html
<html>
<head>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
</head>
<body ng-app = "app">
<div ng-controller = "myCtrl">
<input type = "file" file-model = "myFile"/>
<button ng-click = "uploadFile()">upload me</button>
</div>
</body>
<script src="controller.js"></script>
</html>
controller.js
var app = angular.module('app', []);
app.service('fileUpload', ['$http', function ($http) {
this.uploadFileToUrl = function(file, uploadUrl){
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function(res){
console.log(res);
}).error(function(error){
console.log(error);
});
}
}]);
app.controller('fileCtrl', ['$scope', 'fileUpload', function($scope, fileUpload){
$scope.uploadFile = function(){
var file = $scope.myFile;
console.log('file is ' );
console.dir(file);
var uploadUrl = "/fileUpload.php"; // upload url stands for api endpoint to handle upload to directory
fileUpload.uploadFileToUrl(file, uploadUrl);
};
}]);
</script>
fileupload.php
<?php
$ext = pathinfo($_FILES['file']['name'],PATHINFO_EXTENSION);
$image = time().'.'.$ext;
move_uploaded_file($_FILES["file"]["tmp_name"],__DIR__. ' \\'.$image);
?>
UPLOAD FILES
<input type="file" name="resume" onchange="angular.element(this).scope().uploadResume()" ng-model="fileupload" id="resume" />
$scope.uploadResume = function () {
var f = document.getElementById('resume').files[0];
$scope.selectedResumeName = f.name;
$scope.selectedResumeType = f.type;
r = new FileReader();
r.onloadend = function (e) {
$scope.data = e.target.result;
}
r.readAsDataURL(f);
};
DOWNLOAD FILES:
<a href="{{applicant.resume}}" download> download resume</a>
var app = angular.module("myApp", []);
app.config(['$compileProvider', function ($compileProvider) {
$compileProvider.aHrefSanitizationWhitelist(/^\s*(https?|local|data|chrome-extension):/);
$compileProvider.imgSrcSanitizationWhitelist(/^\s*(https?|local|data|chrome-extension):/);
}]);
app.directive('ngUpload', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var options = {};
options.enableControls = attrs['uploadOptionsEnableControls'];
// get scope function to execute on successful form upload
if (attrs['ngUpload']) {
element.attr("target", "upload_iframe");
element.attr("method", "post");
// Append a timestamp field to the url to prevent browser caching results
element.attr("action", element.attr("action") + "?_t=" + new Date().getTime());
element.attr("enctype", "multipart/form-data");
element.attr("encoding", "multipart/form-data");
// Retrieve the callback function
var fn = attrs['ngUpload'].split('(')[0];
var callbackFn = scope.$eval(fn);
if (callbackFn == null || callbackFn == undefined || !angular.isFunction(callbackFn))
{
var message = "The expression on the ngUpload directive does not point to a valid function.";
// console.error(message);
throw message + "\n";
}
// Helper function to create new i frame for each form submission
var addNewDisposableIframe = function (submitControl) {
// create a new iframe
var iframe = $("<iframe id='upload_iframe' name='upload_iframe' border='0' width='0' height='0' style='width: 0px; height: 0px;
border: none; display: none' />");
// attach function to load event of the iframe
iframe.bind('load', function () {
// get content - requires jQuery
var content = iframe.contents().find('body').text();
// execute the upload response function in the active scope
scope.$apply(function () { callbackFn(content, content !== "" /* upload completed */); });
// remove iframe
if (content != "") // Fixes a bug in Google Chrome that dispose the iframe before content is ready.
setTimeout(function () { iframe.remove(); }, 250);
submitControl.attr('disabled', null);
submitControl.attr('title', 'Click to start upload.');
});
// add the new iframe to application
element.parent().append(iframe);
};
// 1) get the upload submit control(s) on the form (submitters must be decorated with the 'ng-upload-submit' class)
// 2) attach a handler to the controls' click event
$('.upload-submit', element).click(
function () {
addNewDisposableIframe($(this) /* pass the submit control */);
scope.$apply(function () { callbackFn("Please wait...", false /* upload not completed */); });
var enabled = true;
if (options.enableControls === null || options.enableControls === undefined || options.enableControls.length >= 0) {
// disable the submit control on click
$(this).attr('disabled', 'disabled');
enabled = false;
}
$(this).attr('title', (enabled ? '[ENABLED]: ' : '[DISABLED]: ') + 'Uploading, please wait...');
// submit the form
$(element).submit();
}
).attr('title', 'Click to start upload.');
}
else
alert("No callback function found on the ngUpload directive.");
}
};
});
<form class="form form-inline" name="uploadForm" id="uploadForm"
ng-upload="uploadForm12" action="rest/uploadHelpFile" method="post"
enctype="multipart/form-data" style="margin-top: 3px;margin-left:
6px"> <button type="submit" id="mbUploadBtn" class="upload-submit"
ng-hide="true"></button> </form>
#RequestMapping(value = "/uploadHelpFile", method =
RequestMethod.POST) public #ResponseBody String
uploadHelpFile(#RequestParam(value = "file") CommonsMultipartFile[]
file,#RequestParam(value = "fileName") String
fileName,#RequestParam(value = "helpFileType") String
helpFileType,#RequestParam(value = "helpFileName") String
helpFileName) { }

Call function in angular controller after clickin on a dynamiclly created element in DOM

Hi I want to call a function after clicking on a button which is added to dom after angular is loaded. I dont know if this is possible in the way I am trying it, but I do know that my current code doesn't call the alert function.
After sending a search request to my backend, I get a list data entrys, which I display as hrefs.
my_form.setAttribute("href", result[i].url)
my_form.setAttribute("ng-href",'#here')
my_form.setAttribute("ng-click", "alert(1)")
my_form.setAttribute("style", "display:block;")
results in
John Doe
Complete Code:
var appModule = angular.module('graph', [])
appModule.controller('graphCtrl', ['$scope', '$http', '$compile', function ($scope, $http, $compile) {
$scope.search = function () {
var data = {
}
$http.get('/api/search/?q=' + $scope.searchfield, data).success(function (data, status, headers, config) {
var result = data;
var searchResultsContainer = document.getElementById("dropdownId");
while (searchResultsContainer.firstChild) {
searchResultsContainer.removeChild(searchResultsContainer.firstChild);
}
for (i in result) {
var my_form = document.createElement("a");
my_form.setAttribute("href", result[i].url)
my_form.setAttribute("ng-href",'#here')
my_form.setAttribute("ng-click", "alert(1)")
my_form.setAttribute("style", "display:block;")
my_text = document.createTextNode(result[i].caption)
my_form.appendChild(my_text)
searchResultsContainer.appendChild(my_form)
}
})
}
$scope.alert = function(){
alert("Hello! I am an alert box!!");
}
}

Angularjs image preview without filereader

Angularjs: Is there any way, where I can show the image preview to the user for the image selected by him,without using filereader.
Below is my code trying to for it
<input type="file" file-model="myFile"/><br><br>
<button ng-click="uploadFile()">Upload</button>
<img src = {{image}}>
<script>
var mainApp = angular.module("mainApp", []);
mainApp.controller('myController', function ($scope,$http) {
$scope.uploadFile = function(){
var file = $scope.myFile;
var fd = new FormData();
//fd will be an file object now, I want this to be converted to img
$scope.image = Resultimage;
};
});
mainApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
}); //end of scope.$apply
});//end of link
}
};
}]);
In your case you can set the $scope.image to equal URL.createObjectURL(file);
<script>
function readfile(el) {
let file = el.files[0];
document.getElementById("previewImage").src = URL.createObjectURL(file);
}
</script>
<img id="previewImage">
<input type='file' onchange='readfile(this)'/>

ngCordova FileTransfer returning http_status: null when downloading file from FTP

I am trying to download a file from a FTP server using Cordova. I have ngCordova and the Filetransfer plugins installed. Below is my code:
angular.module('TestApp', ['ionic', 'TestApp.controllers', 'charts.ng.justgage', 'pascalprecht.translate', 'ngCookies', 'ngCordova'])
var app = angular.module('TestApp.controllers', [])
app.controller('FileDownloadCtrl', function($scope, $timeout, $cordovaFileTransfer) {
$scope.downloadFile = function() {
var url = "ftp://URL/somefile.xml";
var filename = url.split("/").pop();
alert(filename);
var targetPath = cordova.file.externalRootDirectory + filename;
var trustHosts = true;
var options = new Object();
var headers = { 'Authorization': 'Basic Login_cred' };
options.headers = headers;
alert(cordova.file.externalRootDirectory);
alert(options.headers);
$cordovaFileTransfer.download(url, targetPath, options, trustHosts)
.then(function(result) {
// Success!
alert(JSON.stringify(result));
}, function(error) {
// Error
alert(JSON.stringify(error));
}, function (progress) {
$timeout(function () {
$scope.downloadProgress = (progress.loaded / progress.total) * 100;
})
});
}
});
Angular.module is located in a different JS file in the actual code
This code returns the following alerts:
somefile.xml
file://storage/emulated/0/
[object Object]
{"code":2,"source":ftp://URL/somefile.xml","target":file:///storage/emulated/0/somefile.xml","http_status": null,"body":null,"exception":null}
I have tried downloading a file from a website hosted on the ftp (http://website/somefile.xml), which worked just fine. I am pretty sure I am doing something wrong with the header. I have also tried to put the Login_creds into the target url like this: ftp://username:password#URL/somefile.xml, this did not work but it could be browser specific.
ngCordova File Transfer does not work with ftp:// URL's, when I switched to a password protected http solution it worked.

Using Multipart without Form in Spring MVC

I had gone through many articles in stackoverflow on this specific topic, after a detailed analysis I have finally dared to post another question on the same topic.
I think this would be obvious that what I wanted to do here,
What do I want?
I want to upload a file. I am using angularjs and Spring MVC.
Source :
Controller #Spring :
#RequestMapping(value="/upload", method=RequestMethod.POST, consumes = {"multipart/form-data"})
public String handleFileUpload(#RequestParam(value = "file") MultipartFile file){
String name="";
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + "!";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
#Bean
public MultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(500000000);
return multipartResolver;
}
HTML :
File to upload: <input type="file"
file-model="file" name="fd"><br /> Name: <input type="text" name="name"><br />
<br /> <input type="submit" ng-click="uploadFile()" value="Upload"> Press here to
upload the file!
JS :
$scope.uploadFile = function() {
var fd = new FormData();
var file = $scope.file;
fd.append('file', file);
$http.post("/upload",fd,
{
headers : {
'Content-Type' : undefined
}
}).success(function(data) {
debugger;
}).error(function(data) {
debugger;
})
}
Looks fair??? Here are the observations
Observations on execution:
References :
Spring MVC - AngularJS - File Upload - org.apache.commons.fileupload.FileUploadException
Javascript: Uploading a file... without a file
What is the boundary parameter in an HTTP multi-part (POST) Request?
And many more....:)
Update
Directive which is used in angular,
myApp.directive("fileread", [function () {
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var reader = new FileReader();
reader.onload = function (loadEvent) {
scope.$apply(function () {
scope.fileread = loadEvent.target.result;
});
}
reader.readAsDataURL(changeEvent.target.files[0]);
});
}
}
}]);
Request extracted from chrome :
Problem in my approach :
I created a bean for MultiPartResolver. My understanding after resolving the issue is like you define this bean only when you want a specific type of file or something very specific to the application. Although I seek more insight into this and would love to hear from techies of stackoverflow.
Solution for current problem:
I would give my source code,
HTML :
<div ng-controller="myCtrl">
<input type="file" file-model="myFile" />
<button ng-click="uploadFile()">upload me</button>
</div>
AngularJS :
var myApp = angular.module('myApp', []);
myApp.directive('fileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function(scope, element, attrs) {
var model = $parse(attrs.fileModel);
var modelSetter = model.assign;
element.bind('change', function(){
scope.$apply(function(){
modelSetter(scope, element[0].files[0]);
});
});
}
};
}]);
myApp.controller('myCtrl', ['$scope', '$http', function($scope, $http){
$scope.uploadFile = function(){
var file = $scope.myFile;
var fd = new FormData();
fd.append('file', file);
//We can send anything in name parameter,
//it is hard coded to abc as it is irrelavant in this case.
var uploadUrl = "/upload?name=abc";
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
Spring :
#RequestMapping(value="/upload", method=RequestMethod.POST)
public String handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
return "You successfully uploaded " + name + "!";
} catch (Exception e) {
return "You failed to upload " + name + " => " + e.getMessage();
}
} else {
return "You failed to upload " + name + " because the file was empty.";
}
}
And #arahant Even though we don't see any document base64 content in the request payload while sending request, angular does send MultiPartFile, here is the screenshot
Thanks to all the references. If not for these people I wouldn't have solved this problem at all.
References :
http://uncorkedstudios.com/blog/multipartformdata-file-upload-with-angularjs
Using MultipartHttpServletRequest would be a simple option here, which should work without any other change.
public String handleFileUpload(MultipartHttpServletRequest request) {
Map<String, MultipartFile> uploadedFiles = request.getFileMap();
//...
}

Categories

Resources