How to send image from React app to api server - reactjs

I need help with implementation send image from React app to server api.
In React I use library FilePond for send image, and that work great, but I dont know how to get this image on server, I use NETTE framework and also apitte library for request. If you know how to send and get images another way, write please. Thank you very much!
For example how I use FilePond in react
<FilePond allowMultiple={true} server={"http://localhost:3000" + this.baseProperties.uploadUrl}/>
and part of php code
/**
* #Path("/upload")
* #Method("POST")
* #param ApiRequest $request
* #return string
*/
public function uploadImage(ApiRequest $request)
{
return 'check';
}

It is not very clearly document but file pond will hit whatever API you specified (http://localhost:3000 in your case) simply using the HTTP verb that corresponds to the REST action being taken. so for example if you set this. (note this in react)
server={
{
'url': 'localhost:3000/filepondBackend',
Then file pond would hit the localhost:3000/filepondBackend endpoint with the follow HTTP verbs: POST, GET, DELETE
Here's an example of how the backend would be mapped in spring
#RequestMapping("/filepondBackend")
#DeleteMapping(produces = "application/json")
#ApiOperation(value = "Deletes file from DataBase")
public ResponseEntity<ResponseDTO> deleteFile(
#RequestHeader HttpHeaders headers
{
delete logic
});
#PostMapping(produces = "application/json")
#ApiOperation(value = "Inserts file into DataBase")
public ResponseEntity<ResponseDTO> postFile(
#RequestHeader HttpHeaders headers, #RequestParam("filepond") MultipartFile file
{
post logic
});
#GetMapping(produces = "application/json")
#ApiOperation(value = "Retrieve file from DataBase")
public ResponseEntity<ResponseDTO> getFile(
#RequestHeader HttpHeaders headers
)
{
get logic
});
Hope that helps.

Related

Debugging RestEasy RestClient

I am using the framework in quarkus to build a rest client for the mandrill API
#RegisterRestClient
#Path("1.0")
#Produces("application/json")
#Consumes("application/json")
public interface MailService {
#POST
#Path("/messages/send-template.json")
JsonObject ping(JsonObject mandrillInput);
}
This is the relevant portion of my application.properties
com.example.service.MailService/mp-rest/url=https:/mandrillapp.com/api
And my example resource
#Path("/hello")
public class ExampleResource {
#Inject
#RestClient
MailService mailService;
#Produces(MediaType.TEXT_PLAIN)
#GET
public String hello() {
System.out.print("In the API");
JsonObject key = Json.createObjectBuilder().add("key", "ABCD").build();
System.out.println("The json built is "+key);
JsonObject response = mailService.ping(key);
System.out.println("The response is " + response);
return "hello";
}
}
What I saw is that if the API I am calling (Mandrill in this case) returns an error response (If my key is wrong for example), then the variable I am using to store the response doesnt get the response. Instead the REST API I am exposing to my application wrapping around this, gets populated with the response from Mandrill.
Is this expected behaviour? How can I debug the output of a rest client implementation in Quarkus?
The REST API being called is https://mandrillapp.com/api/docs/users.JSON.html#method=ping2
If you want to be able to get the body of the response when an error occurs, I suggest you use javax.ws.rs.core.Response as the response type.
You could also go another route and handle exceptions using ExceptionMapper

New session after download - angular js - internal rest call

I have an ng-click implementation that does a $http.post() call to the server which returns a file content. so, a file download happens on the browser. below is the code snippet:
$scope.downloadFile = function(mediaObj) {
var downloadReq = {
"cid": $cId,
"pid":$pId,
"mid":$mId
};
$http.post(<server url>, downloadReq)
.then(function(response) {
var downloadUrl = URL.createObjectURL(new Blob([response.data]));
var a = document.createElement('a');
a.href = downloadUrl;
a.target = '_blank';
a.download = response.headers('Content-Disposition').split(';')[1].trim().split('=')[1];
document.body.appendChild(a);
a.click();
a.remove();
}, function(response) {
//unable to download
$scope.downloadErr = true;
});
}
server side code snippet is like this:
public void handleDownloadRequest(String json, HttpServletRequest request, HttpServletResponse httpServletResponse) {
....
// make rest call to another microservice to get file content
IOUtils.copyLarge(new ByteArrayInputStream((byte[])response.getBody()), httpServletResponse.getOutputStream());
// copy all headers from rest call response to httpServletResponse
httpServletResponse.flushBuffer();
}
after this, the next call to server (it need not be download itself, any other server call) is getting a brand new session. the old session has been destroyed.
because of this, server side client session state is lost and working on the client is messed up.
can anyone please help me with understanding why a new session is getting created after the download operation? how i can avoid this? why is the old session getting destroyed?
Thanks in advance.
I am answering my own question. Maybe it will save someone's time. As part of the handleDownloadRequest() method, i was making a rest call to another microservice to get the file data. the httpresponse of that rest call had a new session id that was also getting copied into the httpServletResponse of the handleDownloadRequest() method.
this was getting propagated to the client and in turn the client session state was lost.
SOLUTION: i removed the session cookie header from the response while copying over the headers.
Take care of the http response while making internal rest calls...

How do I get raw request body using servicestack with content-type set to application/x-www-form-urlencoded?

I have my DTO
Route("/testing","POST")]
public class TestingRequest:IRequiresRequestStream
{
public Stream RequestStream { get; set; }
}
and my service
public async Task<object> Post(TestingRequest req)
{
var rawbody = base.Request.GetRawBody();
var data = req.RequestStream.ReadFully();
var strdata = UTF8Encoding.UTF8.GetString(data);
...
}
And I found that when calling it, rawbody or data is not empty only if content-type is not application/x-www-form-urlencoded. If the content type is application/x-www-form-urlencoded, rawbody and data will be empty.
How do I get the raw request body as a whole (string) when the caller set the content-type to be application/x-www-form-urlencoded?
My current env is ubuntu 16.04 with dotnet core 1.1, don't know if it matters
ServiceStack uses a forward only request stream that unless you tell ServiceStack to buffer the Request Stream with a pre-request filter:
PreRequestFilters.Add((httpReq, httpRes) => {
httpReq.UseBufferedStream = true;
});
Either ServiceStack reads or you can read by having your Request DTOs implement IRequiresRequestStream to tell ServiceStack to skip reading the Request Body and that you're going to in your Services.
application/x-www-form-urlencoded requests are special in that if IRequest.FormData is accessed it will trigger reading the Request Body. You can tell ServiceStack to skip reading the FormData when it creates the Request with:
SetConfig(new HostConfig {
SkipFormDataInCreatingRequest = true
});

WebAPI CORS not allowing Post requests

I have exhausted every resource I can find regarding Cors, and I still get the following error message when sending a request from Angular's $http service (via Chrome):
POST http://localhost:61459/api/LoginAuth/PostLoginByHandle 500 (Internal Server Error)
Get requests work just fine. I have found a hundred variations of similar instructions that seem to work for other people, but I just can't crack this one. I'll post my code.
WebApiConfig:
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
// Web API routes
config.MapHttpAttributeRoutes();
config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
);
//var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First();
//jsonFormatter.SerializerSettings = new CamelCasePropertyNamesContractResolver();
var cors = new EnableCorsAttribute("*", "*", "*");
config.EnableCors(cors);
}
}
From my understanding, this should be enough to allow any Cors request globally. In addition, I mark the controller with:
[EnableCors(origins: "*", headers: "*", methods: "*")]
I've tried modifying my web.config with various things I've found online, but I've read that it's not necessary when doing it programatically. Any idea what I'm doing wrong?
I've tagged this post as angularjs in case I'm doing something wrong there, as I'm very new to it. Here is my call:
$http.post("http://localhost:61459/api/LoginAuth/PostLoginByHandle",this.LoginRequest).success(function(data){
testCtrl.user = data;
console.log("Retrieved: " + data);
});
**Edit: I am able to hit the controller with Postman when I remove the top method. Any idea why these would conflict? Postman gives this error:
"Message": "An error has occurred.",
"ExceptionMessage": "Multiple actions were found that match the request: \r\nLoginByKey on type RecruitingTool.Web.Controllers.LoginAuthController\r\nPostLoginByHandle on type RecruitingTool.Web.Controllers.LoginAuthController"
Here is the controller code. I don't get why these would conflict:
[HttpPost]
public LoginResult LoginByKey(LoginRequest req)
{
LoginResult l = new LoginResult();
if (!string.IsNullOrEmpty(req.Key) &&
HttpContext.Current.Cache["credentials." + req.Username.ToUpper()].ToString() == req.Key)
{
l.Success = true;
}
else
{
l.Success = false;
l.ErrorMessage = "The credentials key is not valid.";
}
return l;
}
[HttpPost]
[EnableCors(origins: "*", headers: "*", methods: "POST")]
public LoginResult PostLoginByHandle(LoginRequest req)
{
LoginResult l = new LoginResult();
if (req.Username.ToUpper() == "TESTUSER" && req.Password == "test")
{
//change to authenticate against DB
l.Success = true;
l.CredentialsKey = Guid.NewGuid().ToString();
l.ErrorMessage = "";
HttpContext.Current.Cache["credentials." + req.Username.ToUpper()] = Guid.NewGuid().ToString();
}
else
{
l.Success = false;
l.ErrorMessage = "The username or password is not correct. Please check your information and try again.";
}
return l;
}
**Edit 2: The problem was a conflict between the two method's default routes. I'm not sure why that would be the case, but as soon as I specify an explicit route for both of them, it is resolved. I'm still interested to know the answer if anyone knows. Thanks all!
If you put a breakpoint in your Web API POST controller action is it not hitting it? HTTP 500 normally indicates some issue with your code (unhandled exception).
If it's not hitting that controller action it must be earlier in the pipeline. Have you tried just posting directly to your API method from something like POSTman? Very useful extension for Chrome..
1- Your method parameters are missing the [FromBody] attribute, so it should be like
public LoginResult PostLoginByHandle([FromBody]LoginRequest req)
2- Also, both methods have the exact same signature, in terms of the number of parameters and the data type of req parameters.
hope that helps.
WebAPI supports Convention based routing:
To find the action, Web API looks at the HTTP method, and then looks for an action whose name begins with that HTTP method name. For example, with a GET request, Web API looks for an action that starts with "Get...", such as "GetContact" or "GetAllContacts". This convention applies only to GET, POST, PUT, and DELETE methods. You can enable other HTTP methods by using attributes on your controller. We’ll see an example of that later.
Are you sure you don't have two methods in there, one called PostXXX and one called XXX? Or perhaps the one named POSTxxx is triggering convention-based routing. I've seen mention of "the conventions can result in conflicts in the routing table, matching incorrect actions."
Try renaming your methods to something other than Postxxx, Getxxx, ...
[PS Attribute-routing is much better]
I encountered same problem today. As it turns out the problem was in pre-flight OPTIONS request. I used this solution: Handling CORS Preflight requests to ASP.NET MVC actions
Additionally I added headers into response and removed Microsoft.AspNet.WebApi.Cors from project:
protected void Application_BeginRequest()
{
//CORS
if (Request.Headers.AllKeys.Contains("Origin"))
{
Response.Headers.Add("Access-Control-Allow-Origin", string.IsNullOrWhiteSpace(ConfigurationManager.AppSettings["CORS_ORIGIN"]) ? "*" : ConfigurationManager.AppSettings["CORS_ORIGIN"]);
Response.Headers.Add("Access-Control-Allow-Methods", "OPTIONS, GET, POST, PUT, DELETE");
Response.Headers.Add("Access-Control-Allow-Headers", "Access-Control-Allow-Methods, Access-Control-Allow-Origin, Content-Type, Accept, X-Requested-With, Session");
//handle CORS pre-flight requests
if (Request.HttpMethod == "OPTIONS")
Response.Flush();
}
}

How can blueimp communicate with a Java REST service, if possible

$scope.$on('fileuploadadd', function(e,data) {
$http({
method: 'POST',
}).success().error();
}
i know writing above code for single simple file upload, but with blueimp,
can i manage progress with my rest service? also is above the right approach?
i know there is a data.submit function, but i do not know how can it know to call which server side action.
You can use annotations to map request method on a restful function according to the Javax RS Api. So it depends of which Restful Java Api you use.
An example from the oracle documentation:
package com.sun.jersey.samples.helloworld.resources;
import javax.ws.rs.GET;
import javax.ws.rs.Produces;
import javax.ws.rs.Path;
// The Java class will be hosted at the URI path "/helloworld"
#Path("/helloworld")
public class HelloWorldResource {
// The Java method will process HTTP POST requests
#POST
// The Java method will produce content identified by the MIME Media
// type "text/plain"
#Produces("text/plain")
public String getClichedMessage() {
// Return some cliched textual content
return "Hello World";
}
}
The Javascript :
$('#fileupload').fileupload({
url: 'http://yourSite/helloworld',
type: 'POST',
...

Resources