angularjs POST Image to WCF RESTful - angularjs

This Question has been asked quite a lot, I have searched Google thoroughly (mostly stackoverflow), but none of the solutions worked for me.
I am trying to upload an image (base64) to my WCF Service with angularjs.
response error:
POST http://localhost:8080/Service.svc/Method 413 (Request Entity Too
Large)
The main solution on most questions is allowing a bigger request in your webconfig:
<bindings>
<basicHttpsBinding>
<binding maxBufferPoolSize="2147483647"
maxReceivedMessageSize="2147483647"
maxBufferSize="2147483647" transferMode="Streamed">
<readerQuotas
maxDepth="2147483647"
maxStringContentLength="2147483647"
maxArrayLength="2147483647"
maxBytesPerRead="2147483647"
maxNameTableCharCount="2147483647" />
</binding>
</basicHttpsBinding>
</bindings>
But this still did not work for me.
I am not sure if the issue is caused by my $http request from the app:
Base64
var a = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAIAAAACACAYAAADDPmHLAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyNpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNS1jMDE0IDc5LjE1MTQ4MSwgMjAxMy8wMy8xMy0xMjowOToxNSAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIChNYWNpbnRvc2gpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjFDNzcwRDdEMzI5RjExRTNCMDQxODIzRTEyRDZBM0IyIiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjFDNzcwRDdFMzI5RjExRTNCMDQxODIzRTEyRDZBM0IyIj4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6MUM3NzBEN0IzMjlGMTFFM0IwNDE4MjNFMTJENkEzQjIiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6MUM3NzBEN0MzMjlGMTFFM0IwNDE4MjNFMTJENkEzQjIiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz71dbkLAAAPCElEQVR42uxdCZRU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';
$http
$http({
method: 'POST',
url: ' http://localhost:8080/Service.svc/Method',
data: "message=" + a,
headers: {'Content-Type': 'application/x-www-form-urlencoded'}
})
.success(function(data) {
console.log(data);
})
.error(function(data) {
console.log("failure");
})
};

This is the best solution I have found and it works perfectly.
From Client side (Angularjs), I followed a uncorkedstudios.com article, it explains how to upload an image using Multipart/form-data.
Then for Server side see this question stackoverflow.com/questions/1354749/wcf-service-to-accept-a-post-encoded-multipart-form-data It explains the sever side by using stream when receiving a request from your client.
Your Method parameter will probably look like this: {System.ServiceModel.Dispatcher.StreamFormatter.MessageBodyStream}
For this I used a class found on multipartparser.codeplex.com.
The coding below with the class should be enough to figure out.
public string Upload(Stream stream)
{
MultipartParser parser = new MultipartParser(stream);
if(parser.Success)
{
// Save the file
SaveFile(parser.Filename, parser.ContentType, parser.FileContents);
}
else
{
throw new WebException(System.Net.HttpStatusCode.UnsupportedMediaType, "The posted file was not recognised.");
}
}
Hope it helps.

Related

How to set request part for POST request with angular-file-upload and Spring?

Unfortunately this answer does not help me. The problem appears to be that the request parameter file is not present in my POST request for some reason.
I am trying to upload a file, any file whether it's a binary file or a text file, in a POST request. The REST controller reveals:
#PostMapping(WordEmbeddingApiPaths.UPLOAD_MODEL)
#RequestMapping(method=RequestMethod.POST, headers={"Content-Type=multipart/form-data"})
public ResponseEntity<WordVectorListDto> uploadModel(
#RequestParam("file") MultipartFile file,
RedirectAttributes redirectAttributes) {
LOGGER.debug("POST uploadModel");
return new ResponseEntity<WordVectorListDto>((WordVectorListDto)null, HttpStatus.OK);
}
and on the client I am running:
var uploader = $scope.uploader = new FileUploader({
url: 'http://localhost:8080/rest-api/dl4j/we/uploadModel'
});
uploader.onAfterAddingFile = function($modelFile) {
console.info('onAfterAddingFile', $modelFile);
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
'Content-Type': 'multipart/form-data'
},
params: {'file' : $modelFile.file}
})
.then(
function (data) {
alert("upload success");
},
function (data, status) {
alert("upload error");
}
);
};
However, I am getting 400 Bad Request as server response.
Any idea what the problem is?
Update:
I saw that an internal exception got thrown on the server side stating:
org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present
I thought that I am setting this already - how can I make this right?
Posting FormData with AngularJS
When doing a POST with a FormData API object, it is important to set the Content-Type header to undefined.
var fd = new FormData();
fd.append('file', $modelFile.file);
$http.post($modelFile.url, fd, {
headers: {
//'Content-Type': 'multipart/form-data'
'Content-Type': undefined
},
//params: {'file' : $modelFile.file}
})
When the XHR send() method gets a FormData object created by the FormData API it automatically sets the content type to multipart/form-data and includes the proper boundary.
By having the AngularJS framework override the content type, the boundary is not set properly.
Debugging Small Programs
This question is an example of putting several things together without debugging each part.
This question has several unknown code components:
An undebugged AngularJS POST method
An undebugged Spring Backend
An undebugged mysterious AngularJS service
This answer pointed out errors with the AngularJS POST method but there are a couple of other unknowns. Is the Spring backend working properly? Is the mysterious FileUploader service being used correctly?
Debugging involves isolating unknowns and testing them separately.
Does the Angular POST method work with a known backend such as HTTP BIN - HTTP Request & Response Service?
Does the Spring backend work with an uploader that has been tested?
For more information, see How to debug small programs.
if you are using #EnableAutoConfiguration then you need to do the following as discussed here https://github.com/spring-projects/spring-boot/issues/2958
#EnableAutoConfiguration(exclude = {MultipartAutoConfiguration.class})
define the following beans
#Bean(name = "multipartResolver")
public CommonsMultipartResolver commonsMultipartResolver(){
CommonsMultipartResolver resolver = new CommonsMultipartResolver();
resolver.setMaxUploadSize(50*1024*1024);
return resolver ;
}
#Bean
#Order(0)
public MultipartFilter multipartFilter(){
MultipartFilter multipartFilter = new MultipartFilter();
multipartFilter.setMultipartResolverBeanName("multipartResolver");
return multipartFilter;
}

Ajax POST to C# WCF WebService, 404 not found

I have a simple HTML page with javascript and an Ajax POST for calling a WCF WebService which I have made.
What the HTML page does, is to gather all the info from user input, wrap it in json and it should call the webservice.
The webservice should receive the Ajax POST, deserialize json into an object and insert it into the DB.
I have the WCF service published under my localhost IIS Server, but I get the error 404 not found. I also have the HTML page hosted in a different application, under the same website, in the same IIS localhost.
What could be the problem? I am trying to fix this for 2 days now, with no succes.
So this is my code:
Ajax post:
$.ajax({
type: 'POST',
crossDomain: true,
dataType: 'json',
url: "http://localhost/wcf_test/Service1/InsertUpdateIndividualEpxert",
data: JSON.stringify({individualExpert}),
contentType: "application/json; charset=utf-8",
success: onDataReceived,
error: onDataError
});
function onDataReceived(data)
{
console.log('Everything is good!');
}
function onDataError()
{
console.log('Not working mister!');
}
WCF Interface:
[OperationContract]
[WebInvoke(Method = "POST",
RequestFormat = WebMessageFormat.Json,
ResponseFormat = WebMessageFormat.Json,
BodyStyle = WebMessageBodyStyle.Bare,
UriTemplate = "InsertUpdateIndividualEpxert/{json}")]
void InsertUpdateIndividualEpxert(string json);
WCF Web.Config:
<system.serviceModel>
<bindings>
<webHttpBinding>
<binding name="Service1_HttpBinding">
</binding>
</webHttpBinding>
</bindings>
<behaviors>
<endpointBehaviors>
<behavior name="Service1_EndpointBehavior">
<webHttp />
</behavior>
</endpointBehaviors>
<serviceBehaviors>
<behavior name="Service1_ServiceBehavior">
<serviceMetadata httpGetEnabled="true" httpsGetEnabled="false" />
<serviceDebug includeExceptionDetailInFaults="true" />
</behavior>
</serviceBehaviors>
</behaviors>
<services>
<service behaviorConfiguration="Service1_ServiceBehavior" name="WS_Experts.Service1">
<endpoint address=""
behaviorConfiguration="Service1_EndpointBehavior"
binding="webHttpBinding"
bindingConfiguration="Service1_HttpBinding"
contract="WS_Experts.IService1" />
<endpoint address="mex" binding="mexHttpBinding" contract="IMetadataExchange" />
</service>
</services>
So I had just 2 problems.
In the service interface, UriTemplate should have been "InsertUpdateIndividualEpxert" and NOT "InsertUpdateIndividualEpxert/{json}"
I wrote "Epxert" instead of "Expert".
The tool I used to figure this out was Google Chrome's "PostMan"(not advertising anything, just giving full specs), which gave me the error I could understand "Endpoint not found" ... It was at that moment I knew where I messed up!
Right now I'm getting a "405 Method not allowed", but that my friends is a different ball game!
Happy coding everyone!

uploading text blob as file using $http or $resource with angular.js - mimicking curl style multipart/form upload

So I need to: upload a text blob as a file using $http or $resource with angular.js - mimicking curl style multipart/form upload.
There is a previous post on this problem i'm going to try to be more explicit about the issue with hopes that someone can identify where I may be going astray.
Here is an example of the curl command that I know works with this service:
curl \
http://c.docverter.com/convert \
-F from=markdown \
-F to=pdf \
-F input_files[]=#<(echo hello) #or #example.md for a file
previous post on this problem
example successful log response from sinatra
{"input_files"=>[{:filename=>"api.md", :type=>"text/markdown", :name=>"input_files[]", :tempfile=>#<Tempfile:/tmp/RackMultipart20160426-3-5tb8po>, :head=>"Content-Disposition: form-data; name=\"input_files[]\"; filename=\"api.md\"\r\nContent-Type: text/markdown\r\n"}], "from"=>"markdown", "to"=>"pdf"}
On to what I need to do
I need to upload markdown text (I assume using a blob) as a "file" - I have tried both $resource and $http with a dozen different configurations and no luck.
A typical miserable log response after my hundredth angular attempt:
{"from"=>"markdown", "input_files"=>["{}"], "to"=>"pdf"}
code example:
angular.module('app')
.factory('convert', function ($resource) {
return $resource('http://c.docverter.com/convert', null, {
pdf: {
method: 'POST',
headers: { 'Content-Type': 'multipart/form-data' },
params: {
from: 'markdown',
to: 'pdf',
'input_files[]': new Blob(['##title'], 'text/markdown')
}
}
});
});
This is really only one example of what i've tried. I've been hammering at this for a few hours and haven't had much luck so, perhaps someone on here knows more about multipart form data and can shed some light on the pitfalls of blobs and angular.
Ok a good nights sleep and another hour at it and I have a working upload and download:
var fd = new FormData();
var blob = new Blob([$scope.markdown], {type: 'text/markdown'});
var file = new File([blob], "abc.md");
fd.append('input_files[]', file);
fd.append('from', 'markdown');
fd.append('to', 'pdf');
$http.post('https://mydocverterserver.com/convert', fd, {
transformRequest: angular.identity,
headers: {'Content-Type': undefined},
responseType: 'arraybuffer'
})
.success(function(response){
var b = new Blob([response], { type: 'application/vnd.openxmlformats-officedocument.wordprocessingml.document' });
FileSaver.saveAs(b, 'abc.docx');
})
.error(function(res){
console.log(res);
});
Still a little crude - i'll probably clean it up and move it to a factory, but it works.
This is a docx but it works for markdown and pdf as well.
The FileSaver bit comes from: angular-file-saver
If you are looking for a docverter specific solution like I was - I explain the server side fix here

Issue sending JSON in POST request to Play App

i am working on a project using Play Framework 2.4 using a simple Java template, as in many documentation i have seen, i just wrote a simple controller with my business methods and put the necessary paths on my route's file.
Now i am writing a client in Angular.js to invoke the logic written in the play app. It had work perfectly with GET methods, but when i try to do a POST from angular using the next lines:
$http({
method: 'POST',
url : rootURL + '/user/company',
data : {id : '123456' , name: 'xxxxxx'}
});
I receive a 404 Error. After several hours of forums searching, i found that the Play App is expecting application/x-www-form-urlencoded in the request content-type header.
So i modify my Angular call to the following:
$http({
method: 'POST',
url : rootURL + '/user/company',
data : {id : '123456' , name: 'xxxxx'},
headers: {'Content-Type': 'application/x-www-form-urlencoded'},
transformRequest: function(obj){
var str = [];
for(var p in obj)
str.push(encodeURIComponent(p) + "=" + encodeURIComponent(obj[p]));
return str.join("&");
}
})
};
And the POST works perfectly on this way, but i wonder, is there any way so i can make a POST request to my play app where the content-type is set to application/json? How can achieve this?
UPDATE
Here is my controller code:
public class MyController extends Controller {
public Result myAction(){
//do funny stuffs
}
}
And my route file has the following
POST /path/action controllers.MyController.myAction()
Have you added #BodyParser.Of(BodyParser.Json.class) in your action method?
Also when you are doing POST to a different domain, first check you request to see if it's a POST, I don't know about AngularJS, but with Polymer, it sent a OPTION first during ajax POST to different domain, and I met very similar issue (wrong content type and 404) which is resolved by implementing an OPTION on server which accept POST.
To Fix that, you need to manually implement an OPTION, here's what to do:
First, In your routes file, add an entry to accept OPTION
OPTIONS /*url controllers.Application.optionCheck(url)
Then implement the optionCheck method which accept everything
public Result optionCheck(String url){
response().setHeader("Access-Control-Allow-Origin", "*");
response().setHeader("Access-Control-Allow-Methods", "POST");
response().setHeader("Access-Control-Allow-Headers", "accept, origin, Content-type, x-json, x-prototype-version, x-requested-with");
return ok();
}
And that's it

Download MS Excel/Word via AngularJS call to a REST service

I have an AngularJS application that sends a POST request to a REST service (onClick method of a button). The POST request contains a JSON object with various settings. The REST service uses those settings to create a MS Word/Excel file.
At the moment the REST service sends the contents of the file back as a byte stream (in response to the previously mentioned POST request). When the file arrives I want a save-file-dialog to show up, where I can save the file. The backend is a Spring Boot app using Spring-MVC.
Can this be done in AngularJS?
If you can't use something like location.href to get your data to the server instead of post it, then check it out others using html 5:
more info AngularJS $http-post - convert binary to excel file and download
$http({
url: 'your/webservice',
method: 'POST',
responseType: 'arraybuffer',
data: json, //this is your json data string
headers: {
'Content-type': 'application/json',
'Accept': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
}
}).success(function(data){
var blob = new Blob([data], {
type: 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
});
saveAs(blob, 'File_Name_With_Some_Unique_Id_Time' + '.xlsx');
}).error(function(){
//Some error log
});
This is the Controller function I ended up using:
#RequestMapping(value = "/downloadDocx", method = RequestMethod.POST)
#ResponseStatus(value = HttpStatus.CREATED)
public void downloadDocx(#RequestBody DocxInputBean docxInput,
HttpServletResponse response) throws Exception {
File docxFile = outputManager.createDocxProfile(docxInput);
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
InputStream is = new FileInputStream(docxFile);
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
is.close();
}

Resources