File Upload nodejs, angularjs : Form mistake? - angularjs

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

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

multer array upload does not upload files, getting an empty array

Want to upload an array of 3 files, but in my nodejs i get only an empty array from the angular controller.
In my angular controller i get the files from html with an onchange method, and send it with an http request to the upload function in my nodejs backend.
this.selectFile1 = function(files){
fileArray[0] = files[0];
self.files = files;
}
this.selectFile2 = function(files){
fileArray[1] = files[0];
self.files = files;
}
this.selectFile3 = function(files){
fileArray[2]= files[0];
self.files = files;
}
this.upload = function(){
var fd = new FormData();
var file = fileArray;
fd.append('file', file);
$http.post("/upload", fd, {
transformRequest: angular.identity,
headers: {"Content-Type": undefined}
}).then(function success(response){
if(response.status == 200){
console.log('success');
}
}, function error(response){
console.log(response.data.msgUpload);
})
}
Nodejs upload function:
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, '../uploads');
}
});
var upload = multer({ storage : storage});
router.post('/upload', upload.array('file', 3), function(req,res, next){
console.log(req.files);
if(!req.files){
res.status(400);
}else{
res.status(200);
}
});
why do I get an empty array? and how can I insert the files which are to be uploaded?

nodejs + multer + angularjs for uploading without redirecting

I am using Nodejs + Multer +angularjs for uploading files on the server.
i have a simple HTML file:
<form action="/multer" method="post" enctype="multipart/form-data">
<input type="file" id="photo" name="photo"/>
<button id="Button1">Upload</button>
</form>
Nodejs part:
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname)
}
})
app.post('/multer', upload.single('photo'), function (req, res) {
res.end("File uploaded.");
});
this works perfectly and the file is successfully uploaded.
but this redirect me to "/multer" after uploading the file (because of the form element).
How do i stay on the same page??..possibly using angularjs
so i tried this:
making a HTML angular file:
<section data-ng-controller="myCtrl">
<input type="file" id="photo" name="photo"/>
<button id="Button1" ng-click="f()">Upload</button>
</section>
and a Angularjs controller:
angular.module('users').controller('myCtrl',[$scope,function($scope){
$scope.f=function(){
var photo = document.getElementById('photo');
var file = photo.files[0];
if (file) {
//code to make a post request with a file object for uploading?????
//something like..
//$http.post('/multer', file).success(function(response) {
//console.log("success");
//});
}
}
}]);
CAN SOMEONE HELP ME WITH THE CODE FOR MAKING A POST REQUEST WITH A FILE OBJECT FOR UPLOADING USING MULTER FROM ANGULARJS CONTROLLER ?
thanks
Angularjs directive:
angular.module('users').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]);
});
});
}
};
}]);
Angular html file:
<input type="file" file-model="myFile"/><br><br>
<button ng-click="uploadFile()">Upload</button>
Angularjs Controller:
$scope.uploadFile = function(){
var file = $scope.myFile;
var uploadUrl = "/multer";
var fd = new FormData();
fd.append('file', file);
$http.post(uploadUrl,fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
console.log("success!!");
})
.error(function(){
console.log("error!!");
});
};
Nodejs server route file:
var multer = require('multer');
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, './uploads/')
},
filename: function (req, file, cb) {
cb(null, file.originalname+ '-' + Date.now()+'.jpg')
}
});
var upload = multer({ storage: storage });
app.post('/multer', upload.single('file'));
Enjoy!

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