How to code MVC Web Api Post method for file upload - java

I am following this tutorial on uploading files to a server from android, but I cannot seem to get the code right on the server side. Can somebody please help me code the Web Api post method that would work with that android java uploader? My current web api controller class looks like this:
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http;
namespace WSISWebService.Controllers
{
public class FilesController : ApiController
{
// GET api/files
public IEnumerable<string> Get()
{
return new string[] { "value1", "value2" };
}
// GET api/files/5
public string Get(int id)
{
return "value";
}
// POST api/files
public string Post([FromBody]string value)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
Stream requestStream = task.Result;
try
{
Stream fileStream = File.Create(HttpContext.Current.Server.MapPath("~/" + value));
requestStream.CopyTo(fileStream);
fileStream.Close();
requestStream.Close();
}
catch (IOException)
{
// throw new HttpResponseException("A generic error occured. Please try again later.", HttpStatusCode.InternalServerError);
}
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response.ToString();
}
// PUT api/files/5
public void Put(int id, [FromBody]string value)
{
}
// DELETE api/files/5
public void Delete(int id)
{
}
}
}
I am pretty desperate to get this working as the deadline is tuesday. If anybody could help that would be much appreciated.

you can post a files as multipart/form-data
// POST api/files
public async Task<HttpResponseMessage> Post()
{
// Check if the request contains multipart/form-data.
if (!Request.Content.IsMimeMultipartContent())
{
throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
}
string root = HttpContext.Current.Server.MapPath("~/App_Data");
var provider = new MultipartFormDataStreamProvider(root);
string value;
try
{
// Read the form data and return an async data.
var result = await Request.Content.ReadAsMultipartAsync(provider);
// This illustrates how to get the form data.
foreach (var key in provider.FormData.AllKeys)
{
foreach (var val in provider.FormData.GetValues(key))
{
// return multiple value from FormData
if (key == "value")
value = val;
}
}
if (result.FileData.Any())
{
// This illustrates how to get the file names for uploaded files.
foreach (var file in result.FileData)
{
FileInfo fileInfo = new FileInfo(file.LocalFileName);
if (fileInfo.Exists)
{
//do somthing with file
}
}
}
HttpResponseMessage response = Request.CreateResponse(HttpStatusCode.Created, value);
response.Headers.Location = new Uri(Url.Link("DefaultApi", new { id = files.Id }));
return response;
}
catch (System.Exception e)
{
return Request.CreateErrorResponse(HttpStatusCode.InternalServerError, e);
}
}

Related

Applying OncePerRequestFilter based on Annotation

I wanted to write a Annotation based api which can record and request and response in my library.
Basically the plan was if a developer did something like this:
#RequestMapping(value = "/todo", method = RequestMethod.POST)
#ResponseStatus(HttpStatus.OK)
#CustomCopy
public void createNewTodo() {
I would copy the request and response and dump to a database. I had started to use the HandlerInterceptorAdaptor with afterComplete but that did not lead anywhere since I cannot copy the response as it is flushed out by that time afterComplete is invoked.
Next I was planning to use the OncePerRequestFilter method. Basically use this as the template.
I just could not figure out:
How can I connect the Annotation with my filter ?
If there is another method where I can use the Annotation but also use the request and response body.
I was planning to use to look into AOP but still have not figured it out.
Thanks a lot for the help.
Using AOP you can do it like this:
dependency:
compile 'org.aspectj:aspectjweaver:{version}'
Create Annotation:
#Target(ElementType.METHOD)
#Retention(RetentionPolicy.RUNTIME)
public #interface CustomCopy {
}
Save request response:
#Aspect
#Component
public class SaveRequestResponse {
#Around("#annotation(CustomCopy)")
public Object logExecutionTime(ProceedingJoinPoint joinPoint) throws Throwable {
//Request build
ContentCachingRequestWrapper request = getWrapper(joinPoint);
StringBuilder apiLog = new StringBuilder();
apiLog.append("Rest API: ").append(request.getRequestURL().toString()).append("\n");
apiLog.append("Body:").append(getRequestBody(request)).append("\n");
for (String header : Collections.list(request.getHeaderNames())) {
apiLog.append(header).append(":").append(request.getHeader(header))
.append("\n");
}
//Request build end
//method called
Object proceed = joinPoint.proceed();
//after method called response
String response = new ObjectMapper().writeValueAsString(proceed);
//save apiLog(Full request) && response
return proceed;
}
private String getRequestBody(final ContentCachingRequestWrapper wrapper) {
String payload = null;
if (wrapper != null) {
byte[] buf = wrapper.getContentAsByteArray();
if (buf.length > 0) {
try {
int maxLength = buf.length > 500 ? 500 : buf.length;
payload = new String(buf, 0, maxLength,
wrapper.getCharacterEncoding());
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncoding.", e);
}
}
}
return payload;
}
private ContentCachingRequestWrapper getWrapper(ProceedingJoinPoint joinPoint) {
Object[] args = joinPoint.getArgs();
ContentCachingRequestWrapper request = null;
for (Object arg : args) {
if (arg instanceof ContentCachingRequestWrapper) {
request = (ContentCachingRequestWrapper) arg;
break;
}
}
return request;
}
}
Now use this #CustomCopy annotation in controller method.

Using ASP.NET Web API to call Java Web Service

I have an ASP.NET Web API which is supposed to call a java addition web service. When i run the java web service and type url http://localhost:8080/addition/9/6 i get {"firstNumber":9,"secondNumber":6,"sum":15}as the output data. Right now, i want to use the ASP.NET Web API to call and display that data when i run the ASP.NET Web API application. How do i go about doing that?
Here are my codes:
ASP.NET Web API Codes
RestfulClient.cs
public class RestfulClient
{
private string BASE_URL = "http://localhost:8080/addition/";
public Task<string> addition()
{
{
try
{
var client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = client.GetAsync("addition").Result;
return response.Content.ReadAsStringAsync();
}
catch (Exception e)
{
HttpContext.Current.Server.Transfer("ErrorPage.html");
}
return null;
}
}
}
ApiController.cs
private RestfulClient restfulClient = new RestfulClient();
public ActionResult Index()
{
var Result1 = restfulClient.addition().Result;
return Content(Result1);
}
Java Web Service Codes
AdditionController.java
#RestController
public class AdditionController {
private static final String template = " %s";
private static int getSum;
#RequestMapping("/addition/{param1}/{param2}")
#ResponseBody
public Addition getSum
(#PathVariable("param1") int firstNumber,#PathVariable("param2") int secondNumber) {
return new Addition(
(String.format(template, firstNumber)), String.format(template, secondNumber));
}
}
Someone please help me. Thank you so much in advance.
According to the Java service, the URL you are calling from the client is not formatted correctly based on your base URL and the one used in the GetAsync.
public class RestfulClient {
private static HttpClient client;
private static string BASE_URL = "http://localhost:8080/";
static RestfulClient() {
client = new HttpClient();
client.BaseAddress = new Uri(BASE_URL);
client.DefaultRequestHeaders.Accept.Add(
new MediaTypeWithQualityHeaderValue("application/json"));
}
public async Task<string> addition(int a, int b) {
try {
var endpoint = string.Format("addition/{0}/{1}", a, b);
var response = await client.GetAsync(endpoint);
return await response.Content.ReadAsStringAsync();
} catch (Exception e) {
HttpContext.Current.Server.Transfer("ErrorPage.html");
}
return null;
}
}
The controller would also need to be updated.
public async Task<ActionResult> Index() {
int a = 9;
int b = 6;
var result = await restfulClient.addition(a, b);
return Content(result);
}
Note the proper use of the HttpClient as suggested in the comments and as well as the use of async/await.

get data from $http response using angularjs

I have server written in Java, where I create JSON objects like this:
#Override
public void serialize(Net net, JsonGenerator jg, SerializerProvider sp) throws IOException, JsonProcessingException {
try {
Set<Place> places = net.getPlaces();
Set<Transition> transitions = net.getTransitions();
JSONObject jsonPlaces = new JSONObject();
for (Place p : places)
{
String id = p.getId();
double xCoord = p.getxCoord();
double yCoord = p.getyCoord();
JSONObject jsonPosition = new JSONObject();
jsonPosition.put("x", xCoord);
jsonPosition.put("y", yCoord);
JSONObject jsonPlace = new JSONObject();
jsonPlace.put("position", jsonPosition);
jsonPlaces.put(id, jsonPlace);
}
jg.writeRawValue(jsonPlaces.toString());
} catch (Exception ex) {
throw new IOException("...", ex);
}
}
The resulting object as string (jsonPlaces.toString()) looks like this:
{"id01":{"position":{"x":220,"y":90}},"id02":{"position":{"x":210,"y":250}}}
I send it to my web application using the code below, it uses the serialize() method..
#POST
#Path("/blindLayout")
#Consumes(MediaType.APPLICATION_JSON)
public Net blindLayout(Net net) throws Exception {
.
.
return net;
}
And here is the angularjs code that should recieve the response
.factory('Layout', function ($http, Notification, AnalysisConfig) {
layoutPrototype.performLayout = function (net, options, defered) {
if (net) {
var address = AnalysisConfig.serverAddress + AnalysisConfig.resourceURI + AnalysisConfig.resources.blindLayout;
$http.post(address, JSON.stringify(net), {timeout: AnalysisConfig.timeout})
.then(function (response) {
var data = response;
},
function (response) {
Notification.error({
title: 'Communication error',
...
});
});
};
};
My problem is that I can´t get data from the response. No matter what I tried, the result is always undefined or [object Object]. So how should I get data from response so I can for example use alert() and write something like
id01 (value of x, value of y)
id02 (value of x, value of y)
...
so I can also use it in my app?
the $http returns a promise that's resolved with an object that contains more than just the body but also headers and status. So to retrieve the JSON you created on a backend you can do:
$http.post(address, JSON.stringify(net), {timeout: AnalysisConfig.timeout})
.then(function (response) {
var data = response.data;
},
and then if you want to iterate over object keys you can do few things
for(var id in data){
console.log(data[id]) //{"position":{"x":220,"y":90}}
console.log(data[id].position) //{"x":220,"y":90}
}
or
var arrayOfObjects = Object.keys(data).map(function(id){
return data[id].position;
});
console.log(arrayOfObjects) // [{"x":220,"y":90}, {"x":210,"y":250}]

Issue with rest Service using rest easy

I have a complex object like below
public class TestFilter {
public TestFilter(){
}
private Set<String> m_categories;
private Set<String> m_taskNames;
public Set<String> getCategories() {
return m_categories;
}
public void setCategories(Set<String> categories) {
this.m_categories = categories;
}
public Set<String> getTaskNames() {
return m_taskNames;
}
public void setTaskNames(Set<String> taskNames) {
this.m_taskNames = taskNames;
}
public static TestFilter fromString(String jsonRepresentation){
ObjectMapper mapper = new ObjectMapper();
TestFilter filter= null;
try {
filter = mapper.readValue(jsonRepresentation, TestFilter.class );
} catch (IOException e) {
throw new MyException("Exception while parsing the TestFilter");
}
return filter;
}
}
I am using it in my rest service like below
#GET
#Path("/schedule/info")
public Response getScheduledTasks(#QueryParam(FILTERS)TestFilter testFilter){
if(testFilter == null){
System.out.println("its null");
} else {
System.out.println("not null");
}
return Response.status(Status.OK).entity("Success").build();
}
The url I am using for accessing the object is like below.The url is decoded for ease of reading.
https://myip:port/my-context/rest/schedule/info?filters="{"categories":["C","D"],"taskName":["TaskA"]}"
I had put a debug point on the service, so its hitting the service but the problem is that testFilter is always coming as null.
Please let me know what is the issue with the code.
JSON wrapped in " is just a JSON String. A JSON object should not have the quotes. So just just unwrap the JSON from the quotes
filters={"categories":["C","D"],"taskNames":["TaskA"]}
Another thing, based on your comments. If you want to avoid a 404 NotFound, if you want to change it to something else like 400 Bad Request, then just throw that instead
throw new BadRequestException()
// or new WebApplicationException(400)
It's odd to me that bad query parameters would result in a 404, but this is the specified behavior with JAX-RS. Personally, I just change it to 400 in cases like this.

build url's in java in xpages

in xpages I can use:
var protocol = context.getUrl().getScheme() + "://";
var url:XSPUrl = new XSPUrl(database.getHttpURL());
var host = url.getHost();
...
to build urls to documents/files in documents
How should I build the URL's equivalent in Java?
I build URL's in Java all the time.
Here are some RANDOM code snippets that I use. This is not a single class, just random snippets that should help you get started at least.
FacesContext facesContext = FacesContext.getCurrentInstance();
XSPContext context = XSPContext.getXSPContext(facesContext);
String entryPage = context.getUrl().getPath() + context.getUrl().getQueryString();
if (entryPage.contains("/home.xsp")) {
this.console("Entry Page contains /home.xsp");
if (this.isBasicMode()) {
entryPage.replace("home.xsp", "basic_Menu.xsp");
}
} else {
this.console("entry page does NOT contain /home.xsp");
}
context.redirectToPage(“/myPage.xsp”);
public void redirectExternal(String url) throws IOException {
FacesContext fc = FacesContext.getCurrentInstance();
ExtenalContext externalContext = fc.getExternalContext();
externalContext.redirect(url);
}
public void redirectToPage(final String pageName) {
// pageName = "/myPage.xsp"
try {
// You'd think this would end all Java processing but that's NOT
// what happens
// It looks like the Java code will finish and only then will the
// redirection happen.
final String entryPage = JSFUtil.getXSPContext().getUrl().getPath() + JSFUtil.getXSPContext().getUrl().getQueryString();
FrameworkUtils.getSessionScope().put("entryPage", entryPage);
this.setEntryPage(entryPage);
JSFUtil.getXSPContext().redirectToPage(pageName);
} catch (final RedirectSignal rs) {
// Ignoring this error. Useless!
}
// Returning false so we can stop the calling code from continuing
// return false;
}
public String getParam(final String key) {
if (!this.getQueryString().containsKey(key)) {
return null;
} else {
return this.getQueryString().get(key);
}
}
#SuppressWarnings("unchecked")
public Map<String, String> getQueryString() {
final Map<String, String> qs = (Map<String, String>) FrameworkUtils.resolveVariable("param");
return qs;
}
depends where your documents files are. It think the best way is create a servlet in the nsf, call that by passing an docUNID and attachmentName. Then you can get the document and write the attachment as stream to the response. If you set the header to attachment, like
response.setHeader("Content-disposition", "attachment; filename=\""+attachment.getName()+"\"");
you will get the attachment as download

Categories

Resources