unable to post video file with angular js - angularjs

I am getting success = true but my file path is wrong. I am capturing video and then handing over the location path of that video to my post call to upload the video on server. In POSTMAN request it is submitting the video and giving response success = true with path: app/uploads/jobs/12_524.mp4 however in the app I just get the path without extension of .mp4
here is the call
$rootScope.uploadQuestion = function (file) {
//file is complete path of file in device = localURL: "cdvfile://localhost/sdcard/DCIM/Camera/20170801_142942.mp4"
var form = new FormData();
form.append("job_id", "4124");
form.append("question_id", "11");
form.append("user_id", "159931");
form.append("file", file);
console.log('File: ' + file);
// prints this: File: cdvfile://localhost/sdcard/DCIM/Camera/20170801_142942.mp4
return $http({
method: 'POST',
headers: { 'Content-Type': undefined },
url: 'http://services.someservice.com/upload.php',
//transformRequest: angular.identity,
cache: false,
timeout: 300000
}).then(function (response) {
var data = response.data;
var status = response.status;
if (status == '200') {
if (data.success == "true") {
alert('uploading...');
}
}
}).catch(function (response) {
throw response;
});
}

Related

Angularjs Form data is not binding at server side during file uploade

When im tring to uploade my file into server im getting an Error as TypeError: $http(...).success is not a function(…)
Angular File change code
$scope.ChechFileValid = function (file) {
debugger;
var isValid = false;
if ($scope.SelectedFileForUpload != null) {
if ((file.type == 'image/png' || file.type == 'image/jpeg' || file.type == 'image/gif') && file.size <= (512 * 1024)) {
$scope.FileInvalidMessage = "";
isValid = true;
}
else {
$scope.FileInvalidMessage = "Selected file is Invalid. (only file type png, jpeg and gif and 512 kb size allowed)";
}
}
else {
$scope.FileInvalidMessage = "Image required!";
}
$scope.IsFileValid = isValid;
};
This is my file submit button Code
$scope.SaveFile = function () {
$scope.IsFormSubmitted = true;
$scope.Message = "";
$scope.ChechFileValid($scope.SelectedFileForUpload);
if ($scope.IsFormValid && $scope.IsFileValid) {
FileUploadService.UploadFile($scope.SelectedFileForUpload, $scope.FileDescription).then(function (d) {
alert(d.Message);
ClearForm();
}, function (e) {
alert(e);
});
}
else {
$scope.Message = "All the fields are required.";
}
};
This is my factory code
fac.UploadFile = function (file, description) {
var formData = new FormData();
formData.append("file", file);
formData.append("description", description);
var defer = $q.defer();
return $http({
url: 'http://localhost:59838/Api/Home/Sales',
data: JSON.stringify(formData),
headers: { 'content-type': 'application/json' },
transformRequest: angular.identity,
method: 'POST',
})
.success(function (d) {
defer.resolve(d);
})
Here im getting Error as angular.js:15018 Possibly unhandled rejection: {"data":{"Message":"No HTTP resource was found that matches the request URI 'http://localhost:59838/Api/Home/Sales'.","Message
You are getting the $http(...).success is not a function(…)
because the ".success" method has since been deprecated, use ".then" instead. More info on the following link Check Deprecation notice
As for the second error, it could be the result of improper URI, maybe your route is expecting a query parameter, ie : http://localhost:59838/Api/Home/Sales?XXXX, check the full error for more infos
ie : (No HTTP resource was found that matches the request URI ..."
(parameter XXXX is mandatory))

How to POST binary files with AngularJS (with upload DEMO)

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.

How to make a POST request for a blob in AngularJS

I have the following ajax code that makes a POST request for a blob to the server,and prints the returned data.
function upload(blob){
var formData = new FormData();
formData.append('file', blob);
$.ajax({
url: "http://custom-url/record.php",
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function(data) {
console.log(data);
}
});
}
How can I do the same thing in AngularJS?
Instead of appending the blob to FormData, it is more efficient to send the blob directly as the base64 encoding of the FormData API has an extra 33% overhead.
var config = { headers: { 'Content-Type': undefined } };
$http.post(url, blob, config)
.then(function (response) {
var data = response.data;
var status = response.status;
var statusText = response.statusText;
var headers = response.headers;
var config = response.config;
console.log("Success", status);
return response;
}).catch(function (errorResponse) {
console.log("Error", errorResponse.status);
throw errorResponse;
});
It as important to set the content type header to undefined so that the XHR send method can set the content type header. Otherwise the AngularJS framework will override with content type application/json.
For more information, see AngularJS $http Service API Reference.

Fill angular model from response

I am getting response like
StatusCode: 200, ReasonPhrase: 'OK', Version: 1.1, Content: System.Net.Http.ByteArrayContent, Headers:
{
x-filename: StatementofAccount.pdf
Content-Type: application/octet-stream
Content-Disposition: attachment; filename=StatementofAccount.pdf
}
now i need to use "x-filename: StatementofAccount.pdf" but i am not able to fetch this.
I fill this response to my model like
$scope.dataDetail = response.data;
but when I tried to get
console.log($scope.dataDetail.StatusCode)
or
console.log($scope.dataDetail.Headers.x-filename)
but its showing undefined.
plz get me an idea where i am doing wrong or how to achieve this.
I tried from the following way..plz get me idea where i am wrong.....
c#
....
byte[] bytes = memoryStream.ToArray();
memoryStream.Close();
httpResponseMessage.Content = new ByteArrayContent(bytes.ToArray());
httpResponseMessage.Content.Headers.Add("x-filename", fileName);
httpResponseMessage.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
httpResponseMessage.Content.Headers.ContentDisposition = new ContentDispositionHeaderValue("attachment");
httpResponseMessage.Content.Headers.ContentDisposition.FileName = fileName;
httpResponseMessage.StatusCode = HttpStatusCode.OK;
return httpResponseMessage;
in angularjs
$http({
method: 'post',
url: basePath + '/profile/downloadpdf_fromedit',
// data: JSON.stringify($scope.paginginfostmntaccnt),
responsetype: 'arraybuffer',
headers: {'content-type': 'application/pdf'},
// headers: { 'content-type': 'application/json' }
})
.then(function (response) {
// console.log(response.data);
$scope.dataDetail = response.data;
console.log($scope.dataDetail)
1. var file = new Blob([response.data], { type: 'application/pdf' });
saveAs(file, 'StatementofAccount.pdf');
//url-file:///C:/Users/tushar/Downloads/StatementofAccount.pdf
//failed to load pdf
2.var file = new Blob([response], { type: 'application/pdf' });
var fileurl = URL.createObjectURL(file);
window.open(fileurl);
//url- blob:http://localhost:16311/02f8d85e-74c0-4ccd-b937-22f02cc3866c
//failed to load pdf document
3.
.success(function (data, status, headers, config) {
// any required additional processing here
var results = [];
results.data = data;
results.headers = headers();
results.status = status;
results.config = config;
console.log(results)
$("#loading").hide();
headers = headers();
var filename = headers['x-filename'];
var contentType = headers['content-type'];
if (!filename) {
filename = headers["x-filename"] || 'statementAccount.pdf';
}
var linkElement = document.createElement('a');
try {
var blob = new Blob([data], { type: contentType });
var url = window.URL.createObjectURL(blob);
linkElement.setAttribute('href', url);
linkElement.setAttribute("download", filename);
var clickEvent = new MouseEvent("click", {
"view": window,
"bubbles": true,
"cancelable": false
});
linkElement.dispatchEvent(clickEvent);
$("#loading").hide();
console.log("filename" + filename);
} catch (ex) {
console.log("catch"+ex);
$("#loading").hide();
}
})
//url-file:///C:/Users/tushar/Downloads/statementAccount.pdf
//failed to load pdf document
To access the headers of the response you need to use response.headers instead of response.data the data portion contains body of the response.

Multipart request with AngularJS

I have an API endpoint to which I must send a multipart HTTP request, composed of two parts, file (a file system file) and data (a JSON object).
After some research I found out how to do a multipart request in AngularJS:
$http({
method: 'POST',
url: url,
headers: {
'Content-Type': 'multipart/form-data'
},
data: {
data: model,
file: file
},
transformRequest: customFormDataObject
});
1) The customFormDataObject function initially had this form:
customFormDataObject formDataObject = function (data, headersGetter) {
var fd = new FormData();
angular.forEach(data, function (value, key) {
fd.append(key, value);
});
var headers = headersGetter();
delete headers['Content-Type'];
return fd;
};
The outcome of this implementation is that the individual parts of the request do not have a contentType set to them.
2) After reading some more (https://stackoverflow.com/a/24535293/689216) I tried using a Blob for this, the customFormData object looking like this (a bit of a mess, basically the first part will be of contentType application/json, the second one image/png):
customFormDataObject = function (data, headersGetter) {
var fd = new FormData();
var contentType = 'application/json';
angular.forEach(data, function (value, key) {
fd.append(key, new Blob([JSON.stringify(value)], {
type: contentType
}));
contentType = 'image/png';
});
var headers = headersGetter();
delete headers['Content-Type'];
return fd;
};
This second approach sets the correct contentType for each part of the request, but it does not set any values for the parts.
Basically what happens is with 1) the correct values are set in the multiparts, but the contentType's are not set. With 2) the contentType's are set, but not the values for the multiparts.
Am I missing something? Is this functionality not supposed to work like this?
Thanks!
The easiest way to upload files in Angular:
var fd = new FormData();
fd.append('file', file);
fd.append('data', 'string');
$http.post(uploadUrl, fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined}
})
.success(function(){
})
.error(function(){
});
Absolutely essential are the following two properties of the config object:
transformRequest: angular.identity
overrides Angular's default serialization, leaving our data intact.
headers: {'Content-Type': undefined }
lets the browser detect the correct Content-Type as multipart/form-data, and fill in the correct boundary.
Nothing else worked for me! Courtesy of Lady Louthan's wonderful blogpost.
Have you tried something like this:
$httpProvider.defaults.transformRequest = function(data) {
if (data === undefined){
return data;
}
var formData = new FormData();
for (var key in data){
if(typeof data[key] == 'object' && !(data[key] instanceof File)){
formData.append(key, JSON.stringify(data[key]));
}else{
formData.append(key, data[key]);
}
}
return formData;
};
I just solve exactly the same problem.
After some tests, I had this situation that you've described:
Basically what happens is with 1) the correct values are set in the multiparts, but the contentType's are not set. With 2) the contentType's are set, but not the values for the multiparts.
To fix this problem, I had to use Blob and Post Ajax instead of $http Post.
It seems that $http does not work correctly in this case.
Code:
var formData = new FormData();
var blobId = new Blob([100], { 'type':'text/plain' });
formData.append('testId', blobId);
var blobImage = fileService.base64ToBlob(contentToDecode, 'image/jpeg');
formData.append('file', blobImage, 'imagem' + (i + 1) + '.jpg');
Request:
$.ajax({
url: url,
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
deferred.resolve(response);
$rootScope.requestInProgress = false;
},
error: function(error) {
deferred.reject(error);
$rootScope.requestInProgress = false;
}
});
You can use https://github.com/danialfarid/ng-file-upload/.
In this file uploader, there is a provision for sending the file and data (in JSON format) separately as you mentioned in your question above.
For Ex:-
var upload = $upload.upload({
url: url,
file: file,
method: 'POST' or 'PUT', default POST,
headers: {'Content-Type': 'multipart/form-data'}, // only for html5
fileName: 'doc.jpg',
fileFormDataName: 'myFile',
data: {'data': model}
});
In the above code, you can send either a POST or PUT request with 'multipart/form-data', file and data object as JSON separately.
For more information you can visit the above link and look at the ReadMe.md of the plug-in.
I know that my approach is a bit different from the one that you are currently following, but the objective is same.
what i did to solve this was.
var formData = new FormData(document.getElementById('myFormId'));
then in my service
var deferred = $q.defer();
$http.post('myurl', formData, {
cache: false,
contentType: false,
processData: false,
})
.success(function (response) {
deferred.resolve(response);
})
.error(function (reject) {
deferred.reject(reject);
});
return deferred.promise;

Resources