Not able to upload file - Error:undefined - Angular Js - angularjs

How to use file upload option in Angular Js? I added a file control, and added method in controller.js to get the file details and pass to the service.js. However, I am getting error as undefined. The error is in the controller.js file, where i am not able to pass the correct data to the service.
I have tried the below code, but I am getting error as undefined
index.html:
<form name="mainForm" id="createForm" ng-submit="mainForm.$valid && add()" novalidate>
<div>
<input type="file" class="form-control" id="imageUploadfile" name="imageUploadfile" accept="image/*" />
<input type="button" name="imageUploadButton" ng-click="uploadFiles()" value="Upload" />
</div>
controller.js:
$scope.uploadFiles = function () {
var f = document.getElementById('imageUploadfile').files[0],
r = new FileReader();
r.onloadend = function (e) {
var data = e.target.result;
}
r.readAsArrayBuffer(f);
myAPIService.postUploadImage(r).success(function (response) {
var imageurl = _testBaseUrl + 'Images/' + response.filePath.split(/(\\|\/)/g).pop();
$scope.testTypeImage_url = imageurl;
}).error(function (response) {
alert(response.responseText);
});
};
service.js:
myAPIService.postUploadImage = function (formdata) {
var request = {
url: urlBase + 'UploadImage',
method: 'POST',
data: formdata,
headers: {
'Content-Type': undefined
}
}
return $http(request);
};
How to fix this? Thanks

Related

How to preview images before posting to database using AngularJS?

I am uploading multiple images to MongoDB using multer.
My front-end part has been developed using angular Js.
I am able to upload images to MongoDB, but now I want to preview images on the HTML page before uploading them to the database.
HTML Code :
<div class="col-md-4">
<div class="input-group">
<input type="file" name="file" id='file' multiple="multiple" required="required" />
</div>
</div>
Angular Js Code :
$scope.upload = function () {
//var file = angular.element(document.querySelector('#file')).prop("files")[0];
$scope.files = [];
$scope.uploadedFiles = [];
$scope.selectedFiles = [];
console.log('file length :' + angular.element(document.querySelector('#file')).prop("files").length);
for(var i = 0 ; i < angular.element(document.querySelector('#file')).prop("files").length ; i++){
var file = angular.element(document.querySelector('#file')).prop("files")[i];
console.log('file Name :' + file);
$scope.files.push(file);
}
console.log('Uploaded file :' + $scope.files);
// $scope.files.push(file);
$http({
method: 'POST',
url: '/image/upload',
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++){
formData.append('file', data.files[i]);
$scope.uploadedFiles.push(data.files[i]);
}
console.log('Sending File size :' + data.files.length);
//formData.append('file', data.files[0]);
return formData;
},
data: { model: { title: 'hello'}, files: $scope.files }
}).then(function (res) {
console.log(res);
});
}
What I 've tried
.then(function (res) {
$scope.selectedFiles = "/public/images/" + res.data.imagePaths[0];
}
<div>
Images :{{selectedFiles}}<img ng-src="{{selectedFiles}}">
</div>
I passed selected file to html page, but it's not showing the image.
How can I do that, please help.
Please check this plunker http://plnkr.co/edit/y5n16v?p=preview , the basic idea is shown below
fileReader.readAsDataUrl($scope.file, $scope)
.then(function(result) {
$scope.imageSrc = result;
});

Uploading Excel File in MVC using angularjs. HttpPostedFileBase is empty

I am trying to upload an excel file in mvc using angular js. Following is my view code:
<div class="browsebtn" ng-controller = "serviceablectrlr"><input type="file" id="dataFile" name="uploadFile" data-max-size="2097152" accept=".xls, .xlsx" onclick="$('#fileError').hide();" />
</div>
<input id="btnUploadExcel" type="button" value="Upload" ng-click="UploadConfirmation()" class="btn btn-yellow" />
Following is my controller Code :
var app = angular.module('ProductCatalog');
app.controller('serviceablectrlr', function ($scope, $http) {
var apiURL = $("#ProductCatalogApiUrl").val();
var ClearFile = function () {
$("#dataFile").val('');
}
// pass file object and url to this method
$scope.UploadConfirmation = function () {
alert("sana");
var formData = new FormData();
var totalFiles = document.getElementById("dataFile").files.length;
for (var i = 0; i < totalFiles; i++) {
var file = document.getElementById("dataFile").files[i];
var ext = file.name.split(".")[1];
if ((ext == "xls" || ext == "xlsx") && file.size < (Math.pow(1024, 3) * 2)) {
formData.append("dataFile", file);
$http({
method: 'POST',
url: apiURL + "/BulkInsertion",
data: formData,
dataType: 'json',
headers: { 'Content-Type': undefined},
transformRequest: angular.identity
}).then(function successCallback(response) {
if (response.data.ResponseData == 'Success') {
showToastrMessage('success', 'Offer saved successfully!');
$scope.data = {};
}
else {
alert('In error');
showToastrMessage('error', response.data.ResponseData);
}
},
function errorCallback(response) {
});
}
else {
}
}
}
});
And following is my MVC Controller code:
public ResponseModel Post(
HttpPostedFileBase dataFile
)
{ }
The problem i am facing is that the HttpPostedFileBase is null even though i am sending the correct parameters.
I have referred to the following question which is exactly my problem other than I am working on excel file uploading.
HttpPostedFileBase is null when uploading files with Angular
Any help would be appreciated.
You need to write following code in your cshtml view
#using (Html.BeginForm("ActioName", "ControllerName", FormMethod.Post, new { enctype = "multipart/form-data" }))
{
<div>
<input type="file" name="file" />
<input type="submit" value="OK" class="button" />
</div>
}
In MVC controller
[HttpPost]
public ActionResult UploadFile(HttpPostedFileBase myFile)
{
//Validate the fileType
// Verify that the user selected a file
if (file != null && file.ContentLength > 0)
{
//do something here...
}
}
In cae you want to do with angular js then use following code to post file
// pass file object and url to this method
this.uploadFileToUrl = function (file, uploadUrl) {
return $http({
method: 'POST',
url: uploadUrl,
headers: { 'Content-Type': undefined },
transformRequest: function() {
var formData = new FormData();
if(file){
formData.append("myFile", file);
}
return formData;
}
})
}
Add this in WebApiConfig.Register():
this.SupportedMediaTypes.Add(new MediaTypeHeaderValue("multipart/form-data"));

how to send file and form data in angularjs to node.js server?

hello I am creating mean application for video upload form. I struck at one place when i do post request in angular js to my api then no data is going to my controller.Where am i doing wrong??
<form ng-submit="uploadComplete(form)" enctype="multipart/form-data" id="myForm" ng-controller = "addCtrl">
<div class="form-group">
<label >Title</label>
<input type="text" class="form-control" ng-model = "form.title" name="title" placeholder="Enter Title">
</div>
<div class="form-group">
<label >Description</label>
<textarea class="form-control" ng-model= "form.description" name ="description" rows="5" id="comment" placeholder="Enter Description"></textarea>
</div>
<div class="form-group">
<label >Author</label>
<input type="text" class="form-control" ng-model = "form.author" name ="author" id="exampleInputPassword1" placeholder="Enter Author Name">
</div>
<div class="form-group">
<label >duration</label>
<input type="text" class="form-control" ng-model = "form.duration" name ="duration" id="exampleInputPassword1" placeholder="Enter duration Name">
</div>
<div class="form-group">
<label >ispublic</label>
<input type="text" class="form-control" ng-model = "form.public" name ="public" id="exampleInputPassword1" >
</div>
<input type="file" onchange="angular.element(this).scope().fileChanged(this)" id="userfile" name="userfile" multiple/>
<input type="submit" name="" value="submit">
my angular controller is
function addCtrl($scope, $filter, editableOptions,$http, editableThemes,$window,$uibModal, baProgressModal) {
$scope.fileChanged = function(elem){
$scope.files = elem.files;
$scope.$apply();
}
$scope.uploadComplete = function(f){
$http({
method: 'POST',
format: 'json',
url: '/api/add-video',
headers: {
'Content-Type': 'multipart/form-data'
},
data: JSON.stringify({
title: f.title,
description: f.description,
duration: f.duration,
author:f.author,
file:$scope.files,
ispublic:parseInt(f.public)
}),
transformRequest: function (data, headersGetter) {
var formData = new FormData();
angular.forEach(data, function (value, key) {
formData.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return formData;
}
})
.then(function(success) {
console.log("hit " + JSON.stringify(success));
// $window.location.reload()
}, function(error) {
//console.log("not hit " + JSON.stringify(error));
});
}
console.log($scope.files[0].name);
console.log(parseInt(f.public));
}
}
})();
and my api/url which is part of server side
app.post('/api/add-video', addVideoHandler);
function addVideoHandler(req, res) {
var data = {
title: req.body.title,
description: req.body.description,
author: req.body.author,
duration: req.body.duration,
file: req.body.file,
ispublic: req.body.ispublic
}
console.log(data);
}
I already use all node package in above url file which i didn't mention.Why i didnt getting all data in console it displays :
{ title: undefined,
description: undefined,
author: undefined,
duration: undefined,
file: undefined,
ispublic: undefined }
Where am I doing wrong ??
Please guide me.Thankyou
Try to use a directive as below
.directive('fileModel', ['$parse', function($parse) {
function fn_link(scope, element, attrs) {
var onChange = $parse(attrs.fileModel);
element.on('change', function (event) {
onChange(scope, { $files: event.target.files });
});
};
return {
link: fn_link
}
}])
then replace input type=file to
<input type="file" class="form-control" id="fileId" accept="image/*" file-model="myFiles($files)"/>
and then in your controller add this
var formData = new FormData();
$scope.myFiles = function($files) {
formData.append('img', $files[0]);
}
Replace 'img' to a name which you want it as in backend
Add each and every values with keys in formData to send
as
formData.append('title', form.title);
formData.append('description', form.description);
formData.append('author', form.author);
formData.append('duration', form.duration);
formData.append('public', form.public);
and your $http method
$http({
method: 'POST',
url: '/api/add-video',
headers: {
'Content-Type': undefined
},
data: **formData**),
Node Side
then use multer diskStorage as to upload file to server
var uploadMulter = multer.diskStorage({
destination: function(req, file, callback) {
callback(null, "./UploadDir");
},
filename: function(req, file, callback) {
callback(null, Date.now() + path.extname(file.originalname));
}
});
var upload = multer({ storage: uploadMulter });
./UploadDir is the destination folder where you want to upload your file
and finally your router
app.post('/api/add-video', upload.single('img'), addVideoHandler);
now if you want to upload a single file use upload.single('img')
** or for multiple use **upload.array('img',3) here 3 files will be uploaded. change as you want.
This is my first answer on StackOverflow :-)
if your destination dir UploadDir is not accessible try to join by
app.use('/UploadDir', express.static(path.join(__dirname, 'UploadDir')))
try this $http method if that dont work
$http.post('/api/add-video',formData,{headers:{'Content-Type': undefined}})
Change you Controller as
.controller('addCtrl', function($scope,$http){
var formData = new FormData();
$scope.myFiles = function($files) {
formData.append('img', $files[0]);
}
$scope.uploadComplete= function(form){
formData.append('title', form.title);
formData.append('description', form.description);
formData.append('author', form.author);
formData.append('duration', form.duration);
formData.append('public', form.public);
$http.post('/api/add-video',formData,{headers:{'Content-Type': undefined}}).then(function(res){
alert("Correctly Done")
}, function(err){
alert("Error check console in browser");
console.log(err)
})
}
})

Adding model with image AngularJS and ASP.NET MVC

I need some help to solve this problem. To add new record to my database I'm using AngularJS and ASP.NET MVC (without reloading the page). All is working fine, but the problem appears when I'm trying to upload also image with HTML input type="file". I'm using FormData (I think it is the best way to do this?) to upload image and for the rest model properties I'm using ng-model and so on. The funny thing is that when I'm trying to save just image, without any other data then my controller gets the file but when I will add also some properties for my record like Name, Year, Author + image then the controller with only get the model properties or just single image, never both.
Here is my angulajs code:
angular.module('MovieController', [])
.controller('MovieCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.model = {};
$http.get('/Manage/AddMovieVM').success(function (data) {
$scope.model = data;
});
$scope.addMovie = function () {
$http.post('/Manage/Add', $scope.new.Movie).success(function (data) {
$scope.model.Movies.push(data);
$scope.showAddForm(false);
});
};
//upload files
var formData = new FormData();
$scope.LoadFileData = function (files) {
for (var file in files) {
formData.append("file", files[file]);
}
};
$scope.submit = function () {
$http.post("/Manage/Edit", formData, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (response) {
console.log('succes');
});
};
}]);
Here is my back-end code, ASP.NET MVC:
[HttpPost]
public ActionResult Add(Movie model, HttpPostedFileBase file)
{
var files = Request.Files;
var fileName = Path.GetFileName(file.FileName);
if (ModelState.IsValid)
{
using (var db = new MovieSubtitlesContext())
{
var movie = new Movie()
{
MovieTitle = model.MovieTitle,
MovieDescription = model.MovieDescription,
MovieDirector = model.MovieDirector,
MovieRating = model.MovieRating,
MovieImage = fileName
};
db.Movies.Add(movie);
db.SaveChanges();
return Json(movie, JsonRequestBehavior.AllowGet);
}
}
return View();
}
Here is my view:
<input type="text" class="form-control" placeholder="Title" ng-model="new.Movie.MovieTitle" />
<textarea rows="15" cols="50" class="form-control" ng-model="new.Movie.MovieDescription" placeholder="Description"></textarea>
//director and rating similar to first input
<input id="imgInp" type="file" aria-label="Add photos to your post" class="upload" name="file" onchange="angular.element(this).scope().LoadFileData(this.files)" multiple="" accept="image/*">
I tried a lot. For example to save all in one function like this:
$scope.addMovie = function () {
$http.post('/Manage/Edit', $scope.new.Movie, formData, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.model.Movies.push(data);
$scope.showAddForm(false);
});
};
I think it is a good idea because there are two post requests but it doesn't work anyway. To my button I tried to call two functions like this but still nothing.
<button type="button" class="btn btn-success" ng-click="addMovie(); submit()">Save</button>
I really don't know what I'm doing wrong and how I can save image with other model properties. (When I'm passing the image name in my textbox it is working fine, but that's not the point, (for example I already have in my folder "batman.jpg" then I just need to pass "batman.jpg" in my:
<input type="text" class="form-control" placeholder="Img" ng-model="new.Movie.MovieImage" required />
//Update for Nadeem
MVC Controller:
[HttpPost]
public ActionResult AddMovie(Movie model, HttpPostedFileBase file)
{
if (ModelState.IsValid)
{
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(Server.MapPath("~/Content/ImagesC"), fileName);
file.SaveAs(path);
model.MovieImage = fileName;
}
using (var db = new MovieSubtitlesContext())
{
var movie = new Movie()
{
MovieTitle = model.MovieTitle,
MovieDescription = model.MovieDescription,
MovieDirector = model.MovieDirector,
MovieGenre = model.MovieGenre,
MovieDuration = model.MovieDuration,
MovieTrailer = model.MovieTrailer,
ImdbLink = model.ImdbLink,
MovieRating = model.MovieRating,
MovieImage = model.MovieImage,
ReleaseDate = model.ReleaseDate
};
db.Movies.Add(movie);
db.SaveChanges();
return Json(movie, JsonRequestBehavior.AllowGet);
}
}
return View();
}
Here is also my angularjs controller code for AddMovie
$scope.uploadPic = function (file) {
file.upload = Upload.upload({
url: '/Manage/AddMovie',
data: {
file: file,
MovieTitle: $scope.new.Movie.MovieTitle,
MovieDescription: $scope.new.Movie.MovieDescription,
MovieDirector: $scope.new.Movie.MovieDirector,
ReleaseDate: $scope.new.Movie.ReleaseDate,
MovieGenre: $scope.new.Movie.MovieGenre,
MovieDuration: $scope.new.Movie.MovieDuration,
MovieTrailer: $scope.new.Movie.MovieTrailer,
ImdbLink: $scope.new.Movie.ImdbLink,
MovieRating: $scope.new.Movie.MovieRating
}
});
file.upload.then(function (response) {
$timeout(function () {
file.result = response.data;
});
}, function (response) {
if (response.status > 0)
$scope.errorMsg = response.status + ': ' + response.data;
}, function (evt) {
// Math.min is to fix IE which reports 200% sometimes
file.progress = Math.min(100, parseInt(100.0 * evt.loaded / evt.total));
});
};

Async file upload (using FormData) with Node.JS Express and Formidable in the server side

I want to upload files async to Node.JS Express.
I'm pretty confident with my HTML and Javascript because I've used them several times in the past with ASP.NET in the serverside.
Now I want to use the same clientside code with Node.JS with Express in the serverside.
HTML:
<form id="form">
<div class="form-group">
<label>XML files (1 or many)</label>
<input type="file" class="form-control" id="files" name="dummy" multiple ng-disabled="processing" accept=".xml" />
</div>
<div class="form-group">
<button class="btn btn-default" ng-click="process()" ng-disabled="processing">
<span ng-show="processing">Processing...</span>
<span ng-show="!processing">Convert</span>
</button>
</div>
</form>
Javascript:
$scope.process = function () {
$scope.processing = true;
var formData = new FormData();
for (var i = 0; i < document.getElementById('files').files.length; i++) {
formData.append('file' + i, document.getElementById('files').files[i]);
}
var httpRequest = $http({
method: 'post',
url: "/api/parser/parse",
data: formData,
params: {
},
transformRequest: angular.identity,
headers: { 'Content-Type': undefined }
});
httpRequest.success(function (response) {
$scope.response = response;
if (response.error) {
toaster.pop('error', response.message);
return;
}
toaster.pop('success', "", "Finished processing");
});
httpRequest['finally'](function () {
$scope.processing = false;
});
};
}]);
Serverside code (Node.JS):
var express = require('express');
var formidable = require('formidable');
var _ = require('underscore');
var router = express.Router();
router.post('/parse', function(req, res, next) {
var form = new formidable.IncomingForm();
form.parse(req, function(err, fields, files) {
if (err) {
console.error(err.message);
return;
}
console.log(files.length); // Is outputting "undefined"
});
res.json({
error: false
});
});
How can I access the files being submitted?
As you can see, console.log(files.length) is giving me undefined

Resources