Angular6 File Upload (Image) with Spring boot - spring-boot

I have a problem when uploading an image in angular 6.
Angular:
addAvatar(username: string, file: File) {
const headers = new HttpHeaders({
});
const formData: FormData = new FormData();
formData.append('file', file, file.name);
return this.http.post(`${this.API_URL}/addavatar/` + username, formData, {headers});
}
Spring controller:
#PostMapping("/addavatar/{username}")
public ResponseEntity<?> addAvatar(#PathVariable(value = "username") String username, #RequestPart(name = "file", required = false) MultipartFile file) {
return userService.addAvatar(username, file);
}
If I send request in Postman all works, but if I want to send request in Angular then I have a 404.
File Upload in Postman
Response in html

/file/ URI in Postman URL seems to be overlooked at Angular request path literal API_URL. That's why it occurs the 404 error.

Related

Handling base64 string as application/pdf for a single endpoint on API Gateway

We have an API that has multiple different endpoints, as you'd expect. We have the requirement to add a new endpoint which will return an application/pdf along with the file data.
To do this, we return the following:
return {
statusCode: 200,
headers: {
'Content-Type': 'application/pdf',
'Content-disposition': `attachment; filename=${filename}.pdf`,
'Accept': 'application/pdf',
},
body: fileData,
isBase64Encoded: true,
};
The isBase64Encoded only works when a binary media type is set in the API Gateway. As detailed here:
https://medium.com/#ngchiwang/aws-api-gateway-lambda-return-binary-image-ba8faa660839
The issue we have is that by setting the binary media type to * / * (no spaces) on the API Gateway, this, in turn, affects all other endpoints on the API.
Example This breaks one endpoint on the OPTIONS cors check, returning an InternalServerErrorException without reason. This endpoint is just a GET with no data in the request.
Does this mean we need a separate API just for this one endpoint, or is there a way we can include this in the same APIG?
For further clarification, this is a POST that includes a small amount of JSON in the request: {"someValue":1234} and returns the above application/pdf content type.
I'm just tackling this issue and resolved it like this:
Send base 64 string just as normal json response and handle the pdf part on the client
const sendRes = (status:number, body:any) => {
var response = { statusCode: status, headers: { "Content-Type": "application/json" }, body: JSON.stringify(body) };
return response;
};
return sendRes(201, {pdf:your-base64-string} );
Then on the client (Nuxt in my case):
let res = await this.$store.dispatch('pdf/makePdf')
const linkSource = `data:application/pdf;base64,${res.data.pdf}`;
const downloadLink = document.createElement("a");
const fileName = "your-pdf-filename.pdf";
downloadLink.href = linkSource;
downloadLink.download = fileName;
downloadLink.click();
This open a download window and lets you save the file locally

How to make jira attachments download work using jira rest api

I am trying to download attachments from Jira. I use /rest/api/2/attachment/{id} to get json response of the attachment. It has field "content" that is the attachment url. I use this url and construct HttpGet and execute to get response that always gives me html content asking for login. I am sending Basic Authorization in the httpGet header. Apparently this works for downloading .png files but not any other file types. I am using java spring rest to connect to Jira horizon.
Closeable httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(jira attachmenturl);
httpGet.setHeader("Authorization", "Basic <base64Credentials>);
CloseableHttpResponse response = httpclient.execute(httpGet)
The response for .txt, .jpeg, Microsoft documents is different from response that I get for .png files.
This works:
#GetMapping(value = "/getAttachment")
public String getAttachment(#RequestParam("id") String attachmentID) throws Exception {
Client client = Client.create();
WebResource webResource = client.resource(jiraBaseURLRest + "attachment/" +
attachmentID);
ClientResponse response = webResource.header("Authorization", "Basic " +
base64Creds).type("application/json")
.accept("application/json").get(ClientResponse.class);
String result = response.getEntity(String.class);
JSONObject jsonObj = new JSONObject(result);
System.out.println("JSON Object = "+jsonObj);
URL url = new URL(jsonObj.getString("content"));
Closeable httpclient = HttpClients.createDefault();
HttpGet httpGet = new HttpGet(url.toURI());
httpGet.setHeader("Authorization", "Basic " + base64Creds);
CloseableHttpResponse response1 = ((CloseableHttpClient) httpclient).execute(httpGet);
if(response1.getStatusLine().getStatusCode() == 200)
{
HttpEntity entity = response1.getEntity();
if (entity.isStreaming())
{
System.out.println("Streaming...");
byte data[] = EntityUtils.toByteArray(entity);
FileOutputStream fout = new FileOutputStream(new File("D://pdf1.pdf"));
fout.write(data);
fout.close();
System.out.println("Done!!");
}
}
return "Success";
}

Axios authentifaction request fails to send header to Spring Boot

I am trying to implement Authorization with Axios on RN part and send the token to Spring Boot backend. I've tried to do it before with simple sending email and password as parameters of GET request and it worked fine, but now when I'am trying to send basic headers with btoa to backend part, it keeps receiving null value.
My React Native part:
login(user) {
const headers = {
authorization: 'Basic ' + btoa(user.email + ':' + user.password)
};
return axios.get(API_URL + 'login', {headers: headers})
.then(response => {
console.log('function called')
And my Controller on Spring Boot:
#RequestMapping(value = {"/login"}, method = RequestMethod.GET)
public ResponseEntity<?> login(Principal principal) {
if(principal == null){
//logout will also use here so we should return ok http status.
return (ResponseEntity<?>) ResponseEntity.badRequest();
}
UsernamePasswordAuthenticationToken authenticationToken =
(UsernamePasswordAuthenticationToken) principal;
When I debug the controller, I see that my method parameter principle is receiving null.
I guess the issue might be somewhere either in the header or Controller parameter, but have real idea.
Headers should be:
{
headers: {
"Authorization": "Basic "...
}
}
Alternatively,
{
auth: {
username: "",
password: ""
}
}
Which will add the basic auth header for you
https://github.com/axios/axios#request-config for reference

Angular OAuth2 integration

I am working on a springboot + angular project. And I am implementing oauth for the same.
My Spring boot Oauth services(oauth/token) works fine as expected and was tested in postman successfully. But as am trying to integrate that url with angular, i am continuously facing some trouble. I am always getting 401 unauthorized.
My Angular code is as below
login(userName:any,password:any){
console.log("logged in");
let params = new URLSearchParams();
 params.set('username','1522856566577');   
  params.set('password','sens!tiveP#ss');    
params.set('grant_type','password');
params.set('client_id','clientIdPassword');
params.set('client_secret','secret');
params.set('scope','read');
let headers = new HttpHeaders().
append('Content-type','application/x-www form-urlencoded;
charset=utf- 8').
append('Authorization','Basic '
+btoa("clientIdPassword:secret"));
let options = {
headers:headers
};
  this.http.post('/api/oauth/token',params.toString(), options).subscribe(data => console.log(data),err => console.log('Invalid Credentials')); }}
When you are sending headers from angular, Api needs to allow origins of requests. Add this code in Spring Boot controller above the class like below. After that Api will be allowed to get headers.
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
public class AuthenticationController {
//services...
}
You are setting client id and secret twice in headers and url search params.try the following code to generate tokens in the service
getToken()
{
const httpOptions = {
headers: new Headers({
'Content-Type': 'application/x-www-form-urlencoded',
'Authorization': 'Basic ' + btoa('your_client_id:your_client_pass')
})
};
var body = "grant_type=client_credentials";
return this.http.post('your_url',body,
httpOptions)
.pipe(map(res=>res.json()));
}

Alfresco login api giving Bad Request 400

I am trying to login to alfresco through api. I do not know why it is returning error 400 Bad Request.
The json should be correct and in my ajax call I have also set the content type to 'application/json'.
This is my ajax call.
var jsonData = JSON.stringify({ username : usernameV, password : passwordV });
var request = $.ajax({
settings : {contentType:'application/json'},
type: "POST",
url: "http://---ip---/alfresco/service/api/login",
data: jsonData
});
The json string in the console.
{"username":"admin","password":"admin1"}
Error
400 Bad Request
Request sent by the client was syntactically incorrect
Message in responseJSON object
Unable to parse JSON POST body: A JSONObject text must begin with '{' at character 0"
I suspect this is to do with the way you are setting the contentType as the only ways for this to occur appear to either be empty JSON or an incorrect contentType. Try:
var request = $.ajax({
contentType:"application/json",
type: "POST",
url: "http://---ip---/alfresco/service/api/login",
data: jsonData
});
I have created one java program which was doing same thing.I think you should pass username and password in url.Even if you directly hit below url in browser, It will give you alf_ticket, which is use full in authentication for alfresco.
private static String getAlfticket() throws IOException, JSONException {
String ticket = "";
URL url = new URL("http://hostname/alfresco/service/api/login u="+USERNAME+"&pw="+PASSWORD+"&format=json");
URLConnection con = url.openConnection();
InputStream in = con.getInputStream();
String encoding = con.getContentEncoding();
encoding = encoding == null ? "UTF-8" : encoding;
String json = IOUtils.toString(in, encoding);
JSONObject getData = new JSONObject(json);
System.out.println(getData.getJSONObject("data").get("ticket")
.toString());
ticket =getData.getJSONObject("data").get("ticket").toString();
return ticket;
}
Krutik Jayswal
Alfresco Developer

Resources