How to send file to server use AngularJS and Spring - angularjs

As per subject line I wish to upload/send a file to server using AngularJS and Spring.
When i submit file from client it contains $scope.file = "fileURL.jpg", but at the server receives file = null, and the console returns: data = {"description":"Test","status":"REJECTED"}.
Below is my code:
I have view:
<label class="control-label col-sm-4 col-xs-12" for="file">Please upload the file : <span class="required">*</span> </label>
<div class="col-xs-4 input-max controls ">
<input class="inline-block" type="file" name="file" ng-model="file" data-rule-required="true" id="file" accept=".jpg, .jpeg">
</div>
and AngularJs controller:
var test = {
description:"Test",
status: "REJECTED"
};
var fd = new FormData();
fd.append('data', angular.toJson(test));
fd.append("file", $scope.file);
$http({
method: 'POST',
url: 'EmployeeService/employee/data/fileupload',
headers: {'Content-Type': undefined},
data: fd,
transformRequest: angular.identity
})
.success(function(data, status) {
alert("success");
});
Spring controller:
#ResponseBody
#RequestMapping(value = "/data/fileupload", method = RequestMethod.POST)
public String postFile(#RequestParam(value="file", required=false) MultipartFile file,
#RequestParam(value="data") Object data) throws Exception {
System.out.println("data = " + data);
return "OK!";
}

At HTML:
<input type="file" ng-file-select="onFileSelect($files)" multiple accept="image/*">
At JavaScript:
$scope.onFileSelect = function($files) {
for (var i = 0; i < $files.length; i++) {
var file = $files[i];
var test = {
description:"Test",
status: "REJECTED"
};
var fd = new FormData();
fd.append('data', angular.toJson(test));
fd.append("file", file);
$http({
method: 'POST',
url: 'EmployeeService/employee/data/fileupload',
headers: {'Content-Type': undefined},
data: fd,
transformRequest: angular.identity
})
.success(function(data, status) {
alert("success");
});
}
}
At server:
#ResponseBody
#RequestMapping(value = "/data/fileupload", method = RequestMethod.POST)
public String postFile(#RequestParam(value="file", required=false) MultipartFile file,
#RequestParam(value="data") Object data) throws Exception {
System.out.println("data = " + data);
return "OK!";
}

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

Send FormData with other field in AngularJS

I have a form with two input text and one upload. I have to send it to the server but I have some problem concatenating the file with the text. The server expects this answer:
"title=first_input" "text=second_input" "file=my_file.pdf"
This is the html:
<input type="text" ng-model="title">
<input type="text" ng-model="text">
<input type="file" file-model="myFile"/>
<button ng-click="send()">
This is the Controller:
$scope.title = null;
$scope.text = null;
$scope.send = function(){
var file = $scope.myFile;
var uploadUrl = 'my_url';
blockUI.start();
Add.uploadFileToUrl(file, $scope.newPost.title, $scope.newPost.text, uploadUrl);
};
This is the Directive fileModel:
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]);
});
});
}
};
And this is the Service which call the server:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('file', file);
var obj = {
title: title,
text: text,
file: fd
};
var newObj = JSON.stringify(obj);
$http.post(uploadUrl, newObj, {
transformRequest: angular.identity,
headers: {'Content-Type': 'multipart/form-data'}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
If I try to send, I get Error 400, and the response is: Multipart form parse error - Invalid boundary in multipart: None.
The Payload of Request is: {"title":"sadf","text":"sdfsadf","file":{}}
Don't serialize FormData with POSTing to server. Do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var payload = new FormData();
payload.append("title", title);
payload.append('text', text);
payload.append('file', file);
return $http({
url: uploadUrl,
method: 'POST',
data: payload,
//assign content-type as undefined, the browser
//will assign the correct boundary for us
headers: { 'Content-Type': undefined},
//prevents serializing payload. don't do it.
transformRequest: angular.identity
});
}
Then use it:
MyService.uploadFileToUrl(file, title, text, uploadUrl).then(successCallback).catch(errorCallback);
Here is the complete solution
html code,
create the text anf file upload fields as shown below
<div class="form-group">
<div>
<label for="usr">User Name:</label>
<input type="text" id="usr" ng-model="model.username">
</div>
<div>
<label for="pwd">Password:</label>
<input type="password" id="pwd" ng-model="model.password">
</div><hr>
<div>
<div class="col-lg-6">
<input type="file" file-model="model.somefile"/>
</div>
</div>
<div>
<label for="dob">Dob:</label>
<input type="date" id="dob" ng-model="model.dob">
</div>
<div>
<label for="email">Email:</label>
<input type="email"id="email" ng-model="model.email">
</div>
<button type="submit" ng-click="saveData(model)" >Submit</button>
directive code
create a filemodel directive to parse file
.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]);
});
});
}
};}]);
Service code
append the file and fields to form data and do $http.post as shown below
remember to keep 'Content-Type': undefined
.service('fileUploadService', ['$http', function ($http) {
this.uploadFileToUrl = function(file, username, password, dob, email, uploadUrl){
var myFormData = new FormData();
myFormData.append('file', file);
myFormData.append('username', username);
myFormData.append('password', password);
myFormData.append('dob', dob);
myFormData.append('email', email);
$http.post(uploadUrl, myFormData, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
}
}]);
In controller
Now in controller call the service by sending required data to be appended in parameters,
$scope.saveData = function(model){
var file = model.myFile;
var uploadUrl = "/api/createUsers";
fileUpload.uploadFileToUrl(file, model.username, model.password, model.dob, model.email, uploadUrl);
};
You're sending JSON-formatted data to a server which isn't expecting that format. You already provided the format that the server needs, so you'll need to format it yourself which is pretty simple.
var data = '"title='+title+'" "text='+text+'" "file='+file+'"';
$http.post(uploadUrl, data)
This never gonna work, you can't stringify your FormData object.
You should do this:
this.uploadFileToUrl = function(file, title, text, uploadUrl){
var fd = new FormData();
fd.append('title', title);
fd.append('text', text);
fd.append('file', file);
$http.post(uploadUrl, obj, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
blockUI.stop();
})
.error(function(error){
toaster.pop('error', 'Errore', error);
});
}
Using $resource in AngularJS you can do:
task.service.js
$ngTask.factory("$taskService", [
"$resource",
function ($resource) {
var taskModelUrl = 'api/task/';
return {
rest: {
taskUpload: $resource(taskModelUrl, {
id: '#id'
}, {
save: {
method: "POST",
isArray: false,
headers: {"Content-Type": undefined},
transformRequest: angular.identity
}
})
}
};
}
]);
And then use it in a module:
task.module.js
$ngModelTask.controller("taskController", [
"$scope",
"$taskService",
function (
$scope,
$taskService,
) {
$scope.saveTask = function (name, file) {
var newTask,
payload = new FormData();
payload.append("name", name);
payload.append("file", file);
newTask = $taskService.rest.taskUpload.save(payload);
// check if exists
}
}
Assume that we want to get a list of certain images from a PHP server using the POST method.
You have to provide two parameters in the form for the POST method. Here is how you are going to do.
app.controller('gallery-item', function ($scope, $http) {
var url = 'service.php';
var data = new FormData();
data.append("function", 'getImageList');
data.append('dir', 'all');
$http.post(url, data, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).then(function (response) {
// This function handles success
console.log('angular:', response);
}, function (response) {
// this function handles error
});
});
I have tested it on my system and it works.

AngularJS sending file to Google Blobstore - Blob Key retrieved as 'null'

I want to send a video file to GAE Blobstore using AngularJS, following are the code snippet.
I am getting the upload url through endpoint API call and using it in Form action field and http POST call.
When the BlobKey was retrieved it was always returned as null. The admin console has entry for the item in 'BlobUploadSession', but I could not verify whether the video file was uploaded.
How to identify whats going wrong when the BlobKey was retrieved?
HTML:
<form name="videoForm" action="{{uploadUrl}}" ng-init="init()" novalidate role="form">
<div class="form-group">
<label for="title">Video Title</label>
<input id="title" type="text" name="title" ng-model="video.title"
class="form-control"/>
</div>
<div class="form-group">
<label for="videoFile">File Path</label>
<input id="videoFile" type="file" name="videoFile" class="form-control"
onchange="angular.element(this).scope().setFile(this)"/>
</div>
<button ng-click="addVideo(videoForm)" class="btn btn-primary">Video Add
</button>
</form>
JS:
videoApp.controllers.controller('videoAddCtrl',
function ($scope, $log, $http, oauth2Provider, HTTP_ERRORS) {
$scope.video = $scope.video || {};
$scope.init = function () {
gapi.client.video.getUploadUrl().
execute(function (resp) {
$scope.$apply(function () {
if (resp.error) {
if (resp.code && resp.code == HTTP_ERRORS.UNAUTHORIZED) {
oauth2Provider.showLoginModal();
return;
}
} else {
console.log(resp.result.uploadUrl);
$scope.uploadUrl = resp.result.uploadUrl;
}
});
});
};
$scope.submit = function () {
console.log($scope.files);
console.log($scope.uploadUrl);
return $http({
method: 'POST',
url: $scope.uploadUrl,
headers: { 'Content-Type': undefined },
data: {
file: $scope.files,
},
transformRequest: function(data) {
var formData = new FormData();
angular.forEach(data, function(value, key) {
formData.append(key, value);
});
return formData;
}
}).success(function(data) {
console.log("video " + $scope.video.title + " Successfully Uploaded");
}).error(function(data){
console.log(data);
});
};
$scope.addVideo = function (videoForm) {
console.log($scope.video.title);
$scope.submit(videoForm);
};
$scope.setFile = function(element) {
$scope.$apply(function($scope) {
$scope.files = element.files;
console.log($scope.files);
});
}
});
Java Servlet:
public class UploadVideo extends HttpServlet {
private static final Logger Log = Logger.getLogger(UploadVideo.class.getName());
private BlobstoreService blobstoreService =
BlobstoreServiceFactory.getBlobstoreService();
#Override
public void doPost(HttpServletRequest req, HttpServletResponse res)
throws ServletException, IOException {
Log.info("+Enter");
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> blobKeys = blobs.get("videoFile");
Log.info("Blob Key: " + blobKeys);
if (blobKeys == null || blobKeys.isEmpty()) {
Log.info("Blob is null or empty");
res.sendRedirect("/");
} else {
Log.info("Serve blob");
res.sendRedirect("/serve?blob-key=" + blobKeys.get(0).getKeyString());
}
Log.info("-Exit");
}
}

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

not able to upload image to java restful web service

My angular controller is
app1.controller('kyc_controller', ['$scope', '$http', function($scope, $http)
{
$scope.uploadFile = function(){
var file = $scope.myFile;
var fd = new FormData();
fd.append('file', file);
$http({
method : 'POST',
url: '/GngService/api/GoNoGo/upload_file',
params : {'filename':'pancard'},
data : fd,
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
}).success(function (data, status, headers, config) {
console.log('file ' + config.file.name + 'uploaded. Response: ' + JSON.stringify(data));
});
};
}]);
and my server side api method is
#POST
#Path("/upload_file")
#Consumes({MediaType.MULTIPART_FORM_DATA,MediaType.APPLICATION_FORM_URLENCODED})
#Produces({ MediaType.APPLICATION_JSON, MediaType.APPLICATION_XML })
public Response upload(#FormDataParam("file") InputStream ins, #FormDataParam("filename") String filename, #FormDataParam("file") FormDataContentDisposition contentDispositionHeader ) throws IOException {
System.out.println(filename);
BufferedImage image = ImageIO.read(ins);
// ImageIO.write(image, "jpg", new File("/../../fileName"));
String result = "{'status' : 'ok'}";
String json = new Gson().toJson(result);
return Response.ok(json.toString(), MediaType.APPLICATION_JSON).build();
}
It shows Unsupported media type...please help me to upload images....thanks in advance

Resources