I am using angularjs. I have created a file upload function using angularjs with laravel. The file upload with FormData is working fine. But when I try to send file through PUT method there is no response from the server side.
I have gone through the following answers.
Uploading a file with jquery and sending as a PUT and How to upload a file using an HTTP "PUT" using JQuery? but I cannot able to find solution.
Here is my code.
<input type="file" ng-file-model = "formData.files" multiple>
The directive for my code
app.directive('ngFileModel', ['$parse', function ($parse) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
var model = $parse(attrs.ngFileModel);
var isMultiple = attrs.multiple;
var modelSetter = model.assign;
element.bind('change', function () {
var values = [];
angular.forEach(element[0].files, function (item) {
var value = item;
values.push(value);
});
scope.$apply(function () {
if (isMultiple) {
modelSetter(scope, values);
} else {
modelSetter(scope, values[0]);
}
});
});
}
};
}]);
Here is my function which converts my form data into FormData
constructFormData : function( data ) {
var fd = new FormData();
for (var key in data) {
var value = data[key];
angular.forEach(data, function (file, i) {
fd.append('files['+i+']', file);
});
}
return fd;
},
Here is my Controller
var formData = GeneralService.constructFormData($scope.formData);
FileService.update( formData )
.success(function( data ){
if(data.status == 403) {
$location.path('/403');
}
if(data.success) {
console.log(data);
} else {
ValidationService.showValidationErrors(data.errors);
}
});
Here is my service
update : function(formData) {
return $http({
method: 'PUT',
url: $rootScope.baseurl +'/files',
data: formData,
dataType: 'json',
headers: {'Content-Type': undefined}
});
},
The Server side (laravel)
routes.php
Route::put('/files', ['uses' => 'FilesController#update']);
FilesController
public function update(Request $request) {
$data = $request->all();
print_r($data);
}
the above print_r function displays nothing.
I am get the posted data using print_r($request->all());, It gives empty data. I don't know where I make mistake. If I am asking this question by wrong please apologize.
I have the same issue and finally i found this code
var formData = new FormData();
angular.forEach($scope.data, function (value, key) {
formData.set(key, value);
});
$http.post(uploadUrl, formData, {
transformRequest: angular.identity,
headers : {'Content-Type': undefined}
});
Related
I developed an Ajax POST method to pass the data to the controller. First I append my uploaded file to formData. Then I want to bind a model object to it. I did it. But in the controller, my model is always null.
Please help me how to append correctly and get the model and file correctly
javascript function:
var $file = document.getElementById('file'),
$formData = new FormData();
if ($file.files.length > 0) {
for (var i = 0; i < $file.files.length; i++) {
$formData.append('file-' + i, $file.files[i]);
}
}
var SnapShotReceivedData = [{
REASON: REASON_EXEMPT,
COMMENT: COMMENT_EXEMPT,
ATTACHMENT: $formData
}];
SnapShotReceivedData = JSON.stringify({ 'SnapShotReceivedData': SnapShotReceivedData})
$formData.append('SnapShotReceivedData',SnapShotReceivedData);
$.ajax({
contentType: false;
processData: false,
type: 'POST',
url: '#Url.Action("SetHCMNIDSnapData", "Home")',
data: $formData ,
success: function (result) {
},
failure: function (response) {
// $('#result').html(response);
}
});
Controller:
public JsonResult SetHCMNIDSnapData(List<SnapShot> SnapShotReceivedData)
{
if (Request.Files.Count > 0)
{
foreach (string file in Request.Files)
{
var _file = Request.Files[file];
}
}
}
my model is SnapShotReceivedData.When I debug the controller, the model object always null. please help me to solve this.
unable to send file with angular post call
I am trying to post .mp4 file with some data through ionic 1 with angular 1. While posting through POSTMAN it is fine and working. I am getting Success = false in my application.
in POSTMAN, no headers and data is bellow,
Service url with POST request http://services.example.com/upload.php
body in form data
j_id = 4124, type = text
q_id = 6, type = text
u_id = 159931, type = text
file = demo.mp4, type = file
in my app:
$rootScope.uploadQuestion = function () {
var form = new FormData();
form.append("j_id", "4124");
form.append("q_id", "6");
form.append("u_id", "159931");
form.append("file", $rootScope.videoAns.name); //this returns media object which contain all details of recorded video
return $http({
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' }, // also tried with application/x-www-form-urlencoded
url: 'http://services.example.com/upload.php',
// url: 'http://services.example.com/upload.php?j_id=4124&q_id=8&u_id=159931&file='+$rootScope.videoAns.fullPath,
// data: "j_id=" + encodeURIComponent(4124) + "&q_id=" + encodeURIComponent(8) + "&u_id=" + encodeURIComponent(159931) +"&file=" + encodeURIComponent($rootScope.videoAns),
data: form,
cache: false,
timeout: 300000
}).success(function (data, status, headers, config) {
if (status == '200') {
if (data.success == "true") {
alert('uploading...');
}
}
}).error(function (data, status, headers, config) {
});
}
RECOMMENDED: POST Binary Files Directly
Posting binary files with multi-part/form-data is inefficient as the base64 encoding adds an extra 33% overhead. If the server API accepts POSTs with binary data, post the file directly:
function upload(url, file) {
if (file.constructor.name != "File") {
throw new Error("Not a file");
}
var config = {
headers: {'Content-Type': undefined},
transformRequest: []
};
return $http.post(url, file, config)
.then(function (response) {
console.log("success!");
return response;
}).catch(function (errorResponse) {
console.error("error!");
throw errorResponse;
});
}
Normally the $http service encodes JavaScript objects as JSON strings. Use transformRequest: [] to override the default transformation.
DEMO of Direct POST
angular.module("app",[])
.directive("selectNgFiles", function() {
return {
require: "ngModel",
link: postLink
};
function postLink(scope, elem, attrs, ngModel) {
elem.on("change", function(event) {
ngModel.$setViewValue(elem[0].files);
});
}
})
.controller("ctrl", function($scope, $http) {
var url = "//httpbin.org/post";
var config = {
headers: { 'Content-type': undefined }
};
$scope.upload = function(files) {
var promise = $http.post(url,files[0],config);
promise.then(function(response){
$scope.result="Success "+response.status;
}).catch(function(errorResponse) {
$scope.result="Error "+errorRespone.status;
});
};
})
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
<input type="file" select-ng-files ng-model="files">
<br>
<button ng-disabled="!files" ng-click="upload(files)">
Upload file
</button>
<pre>
Name={{files[0].name}}
Type={{files[0].type}}
RESULT={{result}}
</pre>
</body>
Posting with 'Content-Type': 'multipart/form-data'
When posting data using the FormData API, it is important to set the content type to undefined:
function uploadQuestion(file) {
var form = new FormData();
form.append("j_id", "4124");
form.append("q_id", "6");
form.append("u_id", "159931");
form.append("file", file); //this returns media object which contain all details of recorded video
return $http({
method: 'POST',
headers: { 'Content-Type': undefined ̶'̶m̶u̶l̶t̶i̶p̶a̶r̶t̶/̶f̶o̶r̶m̶-̶d̶a̶t̶a̶'̶ }, // also tried with application/x-www-form-urlencoded
url: 'http://services.example.com/upload.php',
data: form,
̶c̶a̶c̶h̶e̶:̶ ̶f̶a̶l̶s̶e̶,̶
timeout: 300000
̶}̶)̶.̶s̶u̶c̶c̶e̶s̶s̶(̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶(̶d̶a̶t̶a̶,̶ ̶s̶t̶a̶t̶u̶s̶,̶ ̶h̶e̶a̶d̶e̶r̶s̶,̶ ̶c̶o̶n̶f̶i̶g̶)̶ ̶{̶
}).then(function(response) {
var data = response.data;
var status = response.status;
if (status == '200') {
console.log("Success");
}
̶}̶)̶.̶e̶r̶r̶o̶r̶(̶f̶u̶n̶c̶t̶i̶o̶n̶ ̶(̶d̶a̶t̶a̶,̶ ̶s̶t̶a̶t̶u̶s̶,̶ ̶h̶e̶a̶d̶e̶r̶s̶,̶ ̶c̶o̶n̶f̶i̶g̶)̶ ̶{̶
}).catch(function(response) {
console.log("ERROR");
//IMPORTANT
throw response;
});
}
When the XHR API send method sends a FormData Object, it automatically sets the content type header with the appropriate boundary. When the $http service overrides the content type, the server will get a content type header without the proper boundary.
I am trying to upload a file based on the tutorial in the below link,
http://www.encodedna.com/angularjs/tutorial/angularjs-file-upload-using-http-post-formdata-webapi.htm
but the problem is the File is not present in the formdata request and the http.POST request gets failed on calling. I am spending a lot of time on this and I am not able to spot any mistake. could someone please help me resolve this.
// NOW UPLOAD THE FILES.
$scope.uploadFiles = function (id) {
formdata.append('pid', id);
debugger;
var request = {
method: 'POST',
url: '/api/Project/PostProjectFiles',
data: formdata,
headers: {
'Content-Type': undefined
}
};
console.log(request);
// SEND THE FILES.
$http(request)
.then(function (d) {
alert(JSON.stringify(d));
})
.catch(function (d) {
alert(JSON.stringify(d));
console.log(d);
});
}
var formdata = new FormData();
$scope.getTheFiles = function ($files) {
//debugger;
angular.forEach($files, function (value, key) {
formdata.append(key, value);
});
console.log($files);
};
myApp.directive('ngFiles', ['$parse', function ($parse) {
function fn_link(scope, element, attrs) {
var onChange = $parse(attrs.ngFiles);
element.on('change', function (event) {
onChange(scope, {
$files: event.target.files
});
});
};
return {
link: fn_link
}
}]);
I suspect the above getthefiles() method more bcos the $files contain the files but the formdata doesnot contain the files.
HTML Code,
<div class="col-sm-8 panelpadding">
<div>
<input type="file" id="file1" name="file1" ng-model="project.file1" ng-files="getTheFiles($files)" class="col-sm-4" />
</div>
<div class="col-sm-12 text-center">
<button type="button" ng-click="uploadFiles(41)">Upload Documents</button>
</div>
</div>
I have also tried all these ways to catch the filedata but it is not successful. Everytime I get [object object] in the httprequest.
var httpRequest = HttpContext.Current.Request;
var FileObject = httpRequest.Params[0];
var FObject = httpRequest.Form[0];
id = Convert.ToInt32(httpRequest.Params[1]);
Link to dropzone: https://github.com/enyo/dropzone
I am trying to use dropzone as my file upload handler, using angularjs and MVC5.
The issue is I can't seem to get the Http post to go to the MVC 5 backend from angularjs service.
I want to post the files along with other values like action, and a string value named "values"
Below is the code ( in service, angularjs)
sendProductFiles: function (act, file, val) {
return $http.post('/attributes/uploads', $.param({
action: act,
files: file,
values: val
}),
{
transformRequest: angular.identity,
headers: {
'Content-Type': undefined
}
})
}
In control (angular)
$scope.intakeUpload = function (files) {
var fd = new FormData();
for (var i = 0; i < files.length; i++)
fd.append('file', files[i]);
AttributionViewService.sendProductFiles("addAttr", fd, $scope.selectedValues).then(function (res) {
}, function (err) {
});
}
Dropzone.options.myAwesomeDropzone = {
autoProcessQueue: false,
uploadMultiple: true,
parallelUploads: 100,
maxFiles: 100,
// Dropzone settings
init: function () {
var myDropzone = this;
this.element.querySelector("button[type=submit]").addEventListener("click", function (e) {
e.preventDefault();
e.stopPropagation();
myDropzone.processQueue();
});
this.on("sendingmultiple", function (files) {
$scope.intakeUpload(files);
});
this.on("addedfile", function (file) {
file.previewElement.addEventListener("click", function () { this.removeFile(file); });
});
}
}
In MVC 5 control
[HttpPost]
[Route("attributes/uploads")]
public ActionResult AcceptUploads(string action, HttpPostedFile[] files, string values)
{
if (files.Length <= 0)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
foreach (var file in files)
{
System.Diagnostics.Debug.WriteLine(file.FileName);
}
System.Diagnostics.Debug.WriteLine(values);
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
In the current state I am getting a jquery error
jquery.js:8458 Uncaught TypeError: Illegal invocation
Edit, also tried the following:
Angular Service
sendProductFiles: function (act, file, val) {
return $http.post('/attributes/uploads', $.param({
action: act,
files: file,
values: val
}), {
headers: {
'Content-Type': 'multipart/form-data'
}
})
Fixed it!
$scope.intakeUpload = function (files) {
var fd = new FormData();
for (var i = 0; i < files.length; i++)
fd.append('files', files[i]);
fd.append("action", "addAttr");
fd.append("values", $scope.selectedValues);
AttributionViewService.sendProductFiles(fd).then(function (res) {
}, function (err) {
});
}
[HttpPost]
[Route("attributes/uploads")]
public ActionResult AcceptUploads(string action, IEnumerable<HttpPostedFileBase> files, string values)
{
if (files.Count() <= 0)
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
foreach (var file in files)
{
System.Diagnostics.Debug.WriteLine(file.FileName);
}
System.Diagnostics.Debug.WriteLine(values);
return new HttpStatusCodeResult(HttpStatusCode.BadRequest);
}
I try to pass my form parameters to java rest backend but i cant.
controller
$scope.addNewThing = function () {
Myservice.addNew($scope.name);
};
service
addNew: function (name) {
var Foo = $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {}}
});
var results = Foo.save({name: name}, function(data) {
results = data;
});
return results;
}
//also tried this version of code
addNew: function(name) {
return $resource($rootScope.baseUrl + '/path/addNew', {}, {
save: {method: 'POST', params: {name: 'test'}}
});
}
rest backend function
#POST
#Produces("application/json")
#Path("/addNew")
public Response addNew(#FormParam("name") String name) {
try {
//when i check name here it is always null
...
}
}
I can't pass the html form parameter to java rest backend via angular. Also tried to change #FormParam to #QueryParam but it didn't work.
Did you set the default content-type on $http POST requests?
app.config(function($httpProvider) {
$httpProvider.defaults.headers.post = {};
$httpProvider.defaults.headers.post["Content-Type"] = "application/json; charset=utf-8";
});
I don'n know how to receive params value in java but I can show how to pass params from angular service. when you will want to pass params then you should use :paramsName in your URL path.
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {name: '#name'}, {
'post': {method: 'GET'}
});
return addNewItem.post({name: name});
}
or if you don't use /:name in your url you should pass in your header
addNew: function(name) {
var addNewItem = $resource($rootScope.baseUrl + '/path/addNew/:name', {}, {
'post': {method: 'GET', headers: { 'name': name }}
});
return addNewItem.post({name: name});
}
NB: your Content-Type should be application/json
You can try this:
CONTROLLER
$scope.addNewThing = function () {
yourService.addNew($scope.name);
};
SERVICE
angular.module('MyApp')
.service('yourService',['$http', function ($http) {
this.addNew = function (data) {
$http({
url: 'YourURL',
method: 'POST',
data: data, // your $scope.name
headers: {'Content-Type':'application/x-www-form-urlencoded; charset=UTF-8'}
})
.success(function (response) {
console.log('good');
})
.error(function (response) {
console.log('error');
});
};
}]);
JAVA REST API
#POST
#Path("/addNew")
#Consumes("*/*")
public Response addNew(String name) {
// use here your String name
}
Using jQuery params solved my problem
Here is the correct way:
Myservice.addNew().save($.param({
name:$scope.name
}),function(data){
console.log(data);
},function(err){
console.log(err);
});
I can pass the parameters like this with $resource service.