How to preview images before posting to database using AngularJS? - 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;
});

Related

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"));

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

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

File Upload nodejs, angularjs : Form mistake?

I have a multer file upload which does nothing, it doesn't even give me an error. My opiniion is that this is a form mistake, that the html form can't tell the angular controller to send the http post to the nodejs
upload.html
<form id="uploadForm" ng-submit="ctrl.submit">
Select File1: <input type="file" name="file" onchange="angular.element(this).scope().ctrl.selectFile1(this.files)">
<p></p>
Select File2: <input type="file" name="file" onchange="angular.element(this).scope().ctrl.selectFile2(this.files)">
<p></p>
<br>
<input type="submit" value="Upload" id="submit" class="btn btn-primary" ng-click="ctrl.submit()">
</form>
AngularJS Controller
ctrl.js
var file1 = '';
var file2 = '';
this.selectFile1 = function(files){
file1 = files[0];
this.files = files;
}
this.selectFile2 = function(files){
file2 = files[0];
this.files = files;
}
this.upload = function(){
var fd = new FormData();
var file = self.fileArray;
fd.append('file1', file1);
fd.append('file2', file2);
$http.post("/upload", fd, {
transformRequest: angular.identity,
headers: {"Content-Type": undefined}
}).then(function success(response){
if(response.status == 200){
console.log('success');
}
console.log(response);
}, function error(response){
console.log(response);
})
}
NodeJS Backend
test.js
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../uploads');
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
var upload = multer({ storage : storage}).array('file', 2);
router.post('/upload', function(req, res){
upload(req, res, function(err){
if(err){
console.log(err);
return res.end(err);
}
console.log(req.files);
res.sendStatus(200);
});
});
I can save the files from html to the angular controller and save them to the form data but when I send the form data with an array of 2 files to the nodejs backend I get an empty form data in the backend.
SOLUTION:
in nodejs file changed var upload = multer({ storage : storage}).array(...) to var upload = multer({ storage : storage}).any();
You can use onchange to select the file.
<input type="file" name="file" onchange="angular.element(this).scope().selectFile(this.files)"/>
<button ng-click="savePhoto()">Save </button>
In angular controller
xx.controller('yourcontroller', function($scope, $http){
$scope.selectFile = function (files) {
$scope.files = files;
};
$scope.savePhoto = function () {
var fd = new FormData();
fd.append("file", $scope.files[0]);
)) ;
$http.post("/xxx/photos", fd, {
withCredentials: true,
headers: { 'Content-Type': undefined },
transformRequest: angular.identity
}).success(function (data) {
$scope.image = data; // If you want to render the image after successfully uploading in your db
});
};
});

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