I am new to Ionic. I didn't get any solution for this from here.
This is my ionic.config.json
{
"name":"BarcodeScannerApp",
"integrations": {
"cordova": {}
},
"type":"angular",
"proxies":[
{
"proxyUrl":"http://localhost:8085"
}
]
}
Below is the method in service class
public getProduct(barocode: any, basketBarcode: any): Observable<any> {
this.url = '/api/v1/barcode/scan';
let queryParameters = new HttpParams();
queryParameters = queryParameters.set('barcodeInfo', barocode);
queryParameters = queryParameters.set('basketId', basketBarcode);
const requestOptions: any = {
params: queryParameters
};
return this.httpclient.post(this.url, requestOptions);
}
This gives below error
POST http://192.168.0.9:8100/api/v1/barcode/scan 404 (Not Found)
Server side method is below
#RequestMapping(value = "api/v1/barcode/scan", method = {RequestMethod.POST})
public ResponseEntity<ServerResponse> getProductInfo(#RequestParam("barcodeInfo") String barcodeNo, #RequestParam("basketId") String basketId) {
return null;
}
I solved the issue . It was the CORS issue, which i was supposed to add #crossOrigin(" * ") annotation.
If the server is CORS enabled, it will parse the Access-Control-Request-* headers and understand that a request is trying to be made from http://localhost:8100 (Ionic client) with a custom Content-Type.
I think it's should be work. You should use the HTTP header like "Content-type" etc
Related
I have been trying for hours now, to upload a file and a JSON using multipart file upload. I use Expo React Native as the client and SpringBoot as the server.
I already tried many different versions. After reading into this a lot, this is how it should work:
In my Expo app I have this:
const formData = new FormData();
formData.append(
'document',
new Blob([JSON.stringify(json)], {
type: 'application/json'
}));
formData.append('file', {
uri: url,
type: data.type,
name
});
const xhr = new XMLHttpRequest();
xhr.open('POST', API_URL);
xhr.setRequestHeader('Authorization', 'Bearer ' + jwt);
xhr.onload = () => {
const response = JSON.parse(xhr.response);
console.log(response);
// ... do something with the successful response
};
xhr.onerror = e => {
console.log(e, 'upload failed');
};
xhr.ontimeout = e => {
console.log(e, 'upload timeout');
};
xhr.send(formData);
In my SpringBoot Backend I have this:
#PostMapping(value = "/api/upload")
public ResponseEntity<Void> uploadDocument(
#RequestPart("document") DocumentDTO document,
#RequestPart("file") MultipartFile file) {
// ... my business logic
}
Now without the document it would work, but as soon as I add the document I get this error:
o.z.problem.spring.common.AdviceTraits : Bad Request: Required request part 'document' is not present
As a workaround I will upload files as base64 encoded strings for now ... But I really don't understand why this doesn't work, because it should.
Similar issue I think:
https://github.com/facebook/react-native/issues/30623
Any help would be greatly appreciated.
Try your backend with this approach. (May try removing Blob in FE, just leave it as
json string)
Create a class to wrap both document and file.
#Data
public class FormDataModel {
private MultipartFile file;
private DocumentDTO document;
public void setDocument(String document) {
ObjectMapper mapper = new ObjectMapper();
// this requires try-catch block in fact
this.document = mapper.readValue(document, DocumentDTO.class);
}
}
Use #ModelAttribute at Controller
#PostMapping(value = "/api/upload", consumes = {MediaType.MULTIPART_FORM_DATA_VALUE, MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Void> uploadDocument(#ModelAttribute FormDataModel wrapper) {
// ... my business logic
}
I am trying to do create Login page using react in my web application with spring boot in backend. I am using spring security JDBC Authentication for login. I am trying to convert my JSP pages to React. Login is working fine with JSP and spring boot. Now i am trying to create same page with react. but when i post using axios post i am getiing error
Access to XMLHttpRequest at 'http://localhost:8080/onlineshopping/login' from origin 'http://localhost:3000' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.
this is axios Post
export const Login = (username, password) => async dispatch => {
console.log(password)
let params = {
username: username,
password: password
}
const res = await axios.post("http://localhost:8080/onlineshopping/login", {params});
dispatch({
type: Login,
payload: res.data
});
};
SecurityConfig.java
#Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.jdbcAuthentication()
.usersByUsernameQuery("select email, password, enabled from user_detail where email = ?")
.authoritiesByUsernameQuery("select email, role from user_detail where email = ?")
.dataSource(dataSource)
.passwordEncoder(bCryptPasswordEncoder);
}
Pagecontroller.java
#RestController
#CrossOrigin
public class PageController {
#RequestMapping("/login")
public Map<String, Object> login(
#RequestParam(name = "error", required = false) String error,
#RequestParam(name = "logout", required = false) String logout) {
Map<String, Object> map = new HashMap<String, Object>();
System.out.println("Login");
map.put("title", "Login");
if (error != null) {
map.put("message", "Username and Password is invalid!");
}
if (logout != null) {
map.put("logout", "You have logged out successfully!");
}
return map;
}
}
Please tell me why i am getting this error and how to solve it.
You have to add proxy address to your package.json file, e.g.:
},
"proxy": "http://localhost:8080",
"devDependencies": {
Next, you just add all the which is after the localhost, i.e.
axios.get("/onlineshopping/login")
After adding CORS filter configuration in spring boot and content type to application/x-www-form-urlencoded in axios request my problem solved.
export const addProjectTask = (username,password, history) => async dispatch => {
axios.post('http://localhost:8080/onlineshopping/login',
Qs.stringify({
username: username,
password: password
}), {
headers: {
"Content-Type": "application/x-www-form-urlencoded"
}})
.then(function (response) {
console.log(response);
history.push("/");
})
.catch(function (error) {
console.log(error);
});
};
You have to create a proxy for API calls.
Here, proxy uses url pattern to match to the api calls and redirecting them to the corresponding server.
Try with the following:
Install http-proxy-middleware
npm install http-proxy-middleware --save
create src/setupProxy.js
const proxy = require('http-proxy-middleware');
module.exports = function(app) {
app.use(proxy('/api', { target: 'http://localhost:8080/' }));
};
Then run your local Dev server
What I try to achive:
I've got service method that generate PDF/CSV on my backend and I want to save that pdf by pressing a button on my frontend.
My first attempt was to create file and send whole PDF/CSV by controller.
#PostMapping(value = "/export")
public File exportReport(
#RequestParam(value = "format", defaultValue = "PDF") ExportFileFormat format,
#RequestBody ExportBody exportBody) {
if (format.equals(ExportFormat.CSV)) {
return reportService.csvExportSummaryCustomerReport(exportBody);
}
if (format.equals(ExportFormat.PDF)) {
return reportService.pdfExportSummaryCustomerReport(exportBody);
}
throw new InvalidWorkingTimeSyntaxException(String.format("Format:%s is invalid.", format));
}
But this solution gave me an errors with
Access to XMLHttpRequest at
'file:///C:/Users/UserFolder/AppData/Local/Temp/csv6677594787854925068.csv'
from origin 'http://localhost:4200' has been blocked by CORS policy:
Cross origin requests are only supported for protocol schemes: http,
data, chrome, chrome-extension, https.
Ofc I tried set new set response header with 'Access-Control-Allow-Origin' : '*', but it didn't helped out. Same with chrome.exe --allow-file-access-from-files --disable-web-security.
Thats why I decided to another approach which is transfer bytes[] and on angular side create PDF/CSV file.
#PostMapping(value = "/export")
public ResponseEntity<byte[]> exportReport(
#RequestParam(value = "format", defaultValue = "pdf") ExportFileFormat format,
#RequestBody ExportBody exportBody) {
HttpHeaders responseHeaders = new HttpHeaders();
responseHeaders.set("Access-Control-Allow-Origin", "*");
if (format.equals(ExportFileFormat.CSV)) {
responseHeaders.setContentType(MediaType.valueOf("text/csv"));
return new ResponseEntity<>(reportService.csvExportSummaryCustomerReport(exportBody),
responseHeaders,
HttpStatus.OK);
}
if (format.equals(ExportFileFormat.PDF)) {
responseHeaders.setContentType(MediaType.APPLICATION_PDF);
return new ResponseEntity<>(reportService.pdfExportSummaryCustomerReport(exportBody),
responseHeaders,
HttpStatus.OK);
}
throw new InvalidExportFileFormatException(String.format("Format:%s is invalid.", format));
}
Now I added headers and backend seems ok.
After that I created service in frontened side:
exportReport(exportBody: ExportBody, format: String): Observable<Object> {
const exportUrl = `${this.reportsUrl}/export?format=${format}`;
if (format == "PDF") {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/pdf',
'Accept': 'application/pdf'
})
};
return this.http.post(exportUrl, exportBody, httpOptions);
}
if (format == "CSV") {
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'text/csv',
'Accept': 'text/csv'
})
};
return this.http.post(exportUrl, exportBody, httpOptions);
}
}
Right now I wanted to used it just to print result.
downloadPdf() {
this.hoursWorkedForCustomersService.exportReport(this.exportBody, "PDF").subscribe(
result => {
console.log(result);
//saveAs(result, 'new.csv'); <- in the future.
}
);
}
Obviously in future I would've like to download file as PDF/CSV with e.g.
saveAs(result, 'new.pdf');
I've got an error 406. Response is:
POST http://localhost:4200/export?format=PDF 406.
TypeError: Cannot read property 'message' of null
at SafeSubscriber.next.handle.do.err [as _error] (error.interceptor.ts:25)
at SafeSubscriber.__tryOrSetError (Subscriber.js:240)
at SafeSubscriber.error (Subscriber.js:195)
at Subscriber._error (Subscriber.js:125)
at Subscriber.error (Subscriber.js:99)
at DoSubscriber._error (tap.js:84)
at DoSubscriber.error (Subscriber.js:99)
at XMLHttpRequest.onLoad (http.js:1825)
at ZoneDelegate.webpackJsonp../node_modules/zone.js/dist/zone.js.ZoneDelegate.invokeTask (zone.js:421)
at Object.onInvokeTask (core.js:4006)
Any ideas what I'm doing wrong?
Try splitting your backend method into two:
#PostMapping(value = "/export", params={"format=PDF"}, produces=MediaType.APPLICATION_PDF_VALUE)
public ResponseEntity<byte[]> generatePdf(){..}
#PostMapping(value = "/export", params={"format=CSV"}, produces="text/csv")
public ResponseEntity<byte[]> generateCsv(){..}
And please fix the Content-Type of the request: if you're sending JSON in UTF-8 this should work:
const httpOptions = {
headers: new HttpHeaders({
'Content-Type': 'application/json;charset=UTF-8',
'Accept': 'application/pdf'
})
};
BTW: Don't handle CORS headers in your Controller like this:
responseHeaders.set("Access-Control-Allow-Origin", "*");
Consider using #CrossOrigin(origins = "http://localhost:{your frontend server port}") at class or method level on your controller or globally like this:
#Bean
public WebMvcConfigurer corsConfigurer() {
return new WebMvcConfigurerAdapter() {
#Override
public void addCorsMappings(CorsRegistry registry) {
registry.addMapping("/**").allowedOrigins("http://localhost:{your frontend server port}");
}
};
}
cheers
I have this Spring Controller:
#RequestMapping(value = "/create")
#ResponseBody
public ResponseEntity<?> create(
#RequestParam String name,
#RequestParam Integer startYear,
#RequestParam Integer endYear,
#RequestParam(required=false) MultipartFile polygons,
#RequestParam(required=false) Long reference
)
Is it possible to send those parameters from Angular via POST request?
I am trying this:
public createExperiment(): Observable<any> {
const headers = new HttpHeaders({'Content-Type': 'application/json'});
return this.http.post(this.backUrl + 'puerto/create', {name:'name'}, {headers: headers})
.map((res: any) =>
res
);
}
But I already receive this error:
error
:
{timestamp: 1527665099011, status: 400, error: "Bad Request", exception: "org.springframework.web.bind.MissingServletRequestParameterException", message: "Required String parameter 'name' is not present", …}
Why I get this error? and if I fix that, can I then send the MultiPartFile too?
I know I can fix this changing the controller and receiving the params via ResquestBody, but I would like to send the parameters separetely.
#RequestParam is used when you have url params.
http.post(url, null, { headers: headers, params: new HttpParams().set('name', 'fer') })
This will send the name along with the url like http://abcd.com/a/b?name=fer
If you want to send it as a post body, then define a model in your spring code and use #RequestBody annotation in the spring contoller.
Look here for an example.
It worked using a formData and ('Content-Type', 'multipart/form-data');
public createExperimentService(formData: FormData): Observable<any> {
const headers = new HttpHeaders();
headers.append('Content-Type', 'multipart/form-data');
return this.http.post(this.backUrl + 'puerto/create', formData, {headers: headers})
.map((res: any) =>
res
);
}
formData: FormData = new FormData();
createExperiment() {
this.formData.append('name', this.nameExperiment);
this.formData.append('startYear', this.startYear);
this.formData.append('endYear', this.endYear);
this.formData.append('reference', this.reference);
this.createExperimentService(this.formData).subscribe(res => {
console.log(res);
});
}
//This method loads a file
fileChange(event) {
const fileList: FileList = event.target.files;
if (fileList.length > 0) {
const file: File = fileList[0];
this.formData.append('polygons', file, file.name);
}
}
I'm getting an inexplicable error when I try to post an element by using the API of my backend. The API returns an error with code 415, related to Media Type:
Failed to load resource: the server responded with a status of 415 ()
My backend returns me this error:
Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain;charset=UTF-8' not supported
EDIT: Error with Guru solution:
Resolved exception caused by Handler execution: org.springframework.web.HttpMediaTypeNotSupportedException: Content type 'text/plain' not supported
The annoying thing is that I have added this header to my request:
Content-Type: application/json
And the body is correctly parsed into JSON format.
I am using Angular 5, and my backend has been developed by using Spring.
Angular client code:
postProject(project: Project) {
const headers: HttpHeaders = new HttpHeaders();
headers.append('Content-Type', 'application/json');
return this.http.post('http://localhost:8443/projects', project.body(), {headers: headers})
.map(response => response);
}
where body method is:
body() {
const object = {
id: this.id,
name: this.name,
'num_execs': this.num_execs
};
return JSON.stringify(object);
}
Spring API code:
#RequestMapping(value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> addLocation(#RequestBody Project project) {
return new ResponseEntity<>(esProjectService.save(project), HttpStatus.OK);
}
Where RequestMapping of the class is /projects:
#RestController
#RequestMapping("/projects")
public class ProjectResource {
#RequestMapping(value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<?> addLocation(#RequestBody Project project) {
return new ResponseEntity<>(esProjectService.save(project), HttpStatus.OK);
}
... OTHER METHODS...
}
I've already gone through this, one way to solve it is to specify the type #RequestPart (value = "nameOfResource" and consumes = {"multipart/form-data"}
Do not forget to specify the name of Content in Angular.
I hope it helps.
Here is an example below:
RequestMapping(value = "/add", method = RequestMethod.POST, consumes = {"multipart/form-data"}, produces = "application/json")
public ResponseEntity<?> add(#RequestPart(value = "image", required = true) MultipartFile image,
#RequestPart(value = "team", required = true) #Valid Team team, BindingResult bResult) {
}
In angular 5 HttpHeaders is immutable. Therefore, you should use it like this
let headers = new HttpHeaders({
'Content-Type': 'application/json',
'X-XSRF-TOKEN': token
});
or
let headers = new HttpHeaders();
headers = headers.append('Content-Type', 'application/json');
headers = headers.append('X-XSRF-TOKEN', token);
Set the headers in this way and it should resolve your issue. I have put the sample code just to explain how you should add multiple headers. Don't put 'X-XSRF-TOKEN' if you don't require it.
I think the mistake comes from the fact that you want to consume application / json while you send plain / text.
I explain, in your service you specify
#RequestMapping(value = "", method = RequestMethod.POST, consumes = MediaType.APPLICATION_JSON_VALUE)
while in your front code you send plain / text
return JSON.stringify(object);
Just delete the JSON.stringify call and return the json object and all is well.
Change
body() {
const object = {
id: this.id,
name: this.name,
'num_execs': this.num_execs
};
return JSON.stringify(object);
}
to
body() {
const object = {
id: this.id,
name: this.name,
'num_execs': this.num_execs
};
return object;
}