Send JSON data as multipart/form-data using axios POST Request - java

Below API works using postman:
Spring boot, backend code:
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.CrossOrigin;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;
#CrossOrigin(origins = "*", maxAge = 3600)
#RestController
#Slf4j
public class UploadFile {
#Autowired
private FTPClient con;
#PostMapping("/api/auth/uploadfiles")
public String handleFileUpload(#RequestParam("file") MultipartFile file, RedirectAttributes redirectAttributes) {
try {
boolean result = con.storeFile(file.getOriginalFilename(), file.getInputStream());
redirectAttributes.addFlashAttribute("message",
"You successfully uploaded " + file.getOriginalFilename() + "!");
} catch (Exception e) {
log.error(e.getMessage(), e);
redirectAttributes.addFlashAttribute("message",
"Could not upload " + file.getOriginalFilename() + "!");
}
return "redirect:/";
}
}
ReactJS, frontend code: I have array of objects in the this.state.ipData.
exportFTP = async () => {
const fromdata = this.state.ipData;
alert("Data Send to FTP server");
axios({
method: 'post',
url: 'http://localhost:8080/api/auth/uploadfiles',
data: fromdata,
header: {
'Accept': 'application/json ,text/plain, */*',
'Content-Type': 'multipart/form-data',
//'Authorization': 'Bearer '+JWTToken,
},
})
}
Button to trigger the function:
<button
style={{ marginRight: "2%", marginTop: "0.25%" }}
type="button"
className="btn btn-info"
onClick={() => this.exportFTP()}
>
Export to FTP
</button>
I need to change my frontend (ReactJS) code to as I did POST request using postman. The current JS code causes below error response:
Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is org.springframework.web.multipart.MultipartException: Current request is not a multipart request] with root cause
Note that API works when using Postman. How to fix JS code?

You are sending JSON data as Blob in a multipart request. So, you need to use Blob API.
Create a function to create a blob from JSON data:
function jsonBlob(obj) {
return new Blob([JSON.stringify(obj)], {
type: "application/json",
});
}
And use this function in the request:
exportFTP = async () => {
const formData = new FormData();
formData.append("file", jsonBlob(this.state.ipData))
axios({
method: "post",
url: "http://localhost:8080/api/auth/uploadfiles",
data: formData,
/* You had a Typo: it is "headers" not "header".
And, multipart/form-data header should get set automatically
as we used FormData. You might not need to add that manually. */
// You may also not need Accept header; (should be set automatically).
headers: {
Accept: "application/json ,text/plain, */*",
"Content-Type": "multipart/form-data",
// 'Authorization': 'Bearer '+ JWTToken,
},
});
};

Try to remove the header and send the request
exportFTP = async () => {
const fromdata = this.state.ipData;
alert("Data Send to FTP server");
axios({
method: 'post',
url: 'http://localhost:8080/api/auth/uploadfiles',
data: fromdata
}).then(function (res) {
if (res.ok) {
alert("Perfect! ");
} else if (res.status == 401) {
alert("Oops! ");
}
}, function (e) {
alert("Error submitting form!");
});
}

Related

File Upload in Angular giving error when posting POST request

I have an HTML form like this to upload files from front-end to back-end and do some operations:
<button mat-raised-button color="primary" type="button" style='margin-right:20px' (click)="selectFile()">Select File To Upload</button>
<input #fileUploadInput type="file" id="fileUpload" hidden name="avatar" (change)="fileChangeEvent($event)">
<button mat-raised-button color="primary" type="button" style='margin-right:20px' enctype="multipart/form-data" (click)="uploadFile()">Submit</button>
<br><br>
<a class="generate-full-width" style="color: darkred;" *ngIf="fileName"><strong>{{fileName}}</strong></a>
The component.ts is:
export class uploadFileDialog {
constructor(
public dialogRef: MatDialogRef<AddProductDialog>,
private uploadService: UploadService,
private builder: FormBuilder, public dialog: MatDialog,
#Inject(MAT_DIALOG_DATA) public data) {
}
#ViewChild('fileUploadInput', {static: false})
fileUploadVariable: ElementRef;
fileName;
currentFile: File;
filesToUpload = [];
resetFile(){
this.fileUploadVariable.nativeElement.value = "";
}
selectFile(){
this.resetFile();
let el: HTMLElement = this.fileUploadVariable.nativeElement as HTMLElement;
el.click();
}
fileChangeEvent(fileInput: any) {
let file = fileInput.target.files[0]
console.log(file)
//console.log(file.data.toString());
this.filesToUpload = [];
this.filesToUpload.push(file);
this.fileName = file['name'];
}
uploadFile(){
this.currentFile = this.fileName;
console.log(this.currentFile);
this.uploadService.uploadFile(this.currentFile)
.subscribe((data) => {
console.log(data)
},
error => {
console.log(error)
});
}
}
Service.ts is:
uploadFile(file: File): Observable<any> {
let headers = new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
//'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
})
let options = {headers:headers, observer: 'response'};
const formData: FormData = new FormData();
formData.append('file', file);
//return this.http.post(this.url+'/fileUpload/upload', formData,options)
const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
reportProgress: true,
responseType: 'json'
});
return this.http.request(req);
}
The controller file at Java backend is:
#RestController
#CrossOrigin(origins = "*", allowedHeaders="*", exposedHeaders="Access-Control-Allow-Origin")
#RequestMapping("/fileUpload")
public class FileController {
private final FileService fileService;
#Autowired
public FileController(FileService fileService) {
this.fileService = fileService;
}
#PostMapping(value = "/upload")
public void handleFileUpload(#RequestParam("file") MultipartFile file) throws IOException {
fileService.storeFile(file);
}}
and the Service File at Java Backend is:
#Service
public class FileService {
private static final String FILE_DIRECTORY = "D:\\temp";
public void storeFile(MultipartFile file) throws IOException {
Path filePath = Paths.get(FILE_DIRECTORY + "\" + file.getOriginalFilename());
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
}
}
I am able to see the file name when uploading in the console. Also, in the body of the request, the formData is showing the xml file as content in the Networks tab. I Java console, I am getting the error:
2020-12-15 12:26:53.144 WARN 9688 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
Error in front-end console:
HttpHeaderResponse {headers: HttpHeaders, status: 400, statusText: "OK", url: "http://localhost:8080/fileUpload/upload", ok: false, …}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
ok: false
status: 400
statusText: "OK"
type: 2
url: "http://localhost:8080/fileUpload/upload"
__proto__: HttpResponseBase
What am I doing wrong?
You are sending only file name but not actual file blob.
Try to do below changes,
component.ts :
uploadFile() {
this.currentFile = this.fileName;
console.log(this.currentFile, this.filesToUpload[0]);
this.uploadService.uploadFile(this.currentFile, this.filesToUpload[0])
.subscribe((data) => {
console.log(data)
},
error => {
console.log(error)
});
}
service.ts
uploadFile(fileName: string, file: File): Observable<any> {
let headers = new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
})
let options = {headers:headers, observer: 'response'};
const formData: FormData = new FormData();
formData.append('fileName', fileName);
formData.append('file', file);
const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
reportProgress: true,
responseType: 'json'
});
return this.http.request(req);
}
Please refer this link to know more about formData

Passing json data ajax to Spring boot

I'm trying to passing Json Data with Ajax to SpringBoot, but it's throwing error, What is the mistake in my program Pls tell me and suggest me. what is the mistake.
var emailId = {"emailId" : userEmail};
$.ajax({
url : "/api/v1/leadsquard/user/emailId",
type : "GET",
data : JSON.stringify(emailId),
dataType : "text",
contentType: "application/json",
success: function (response) {
alert("Success "+ JSON.stringify(response));
},
error: function(response) {
alert("Success "+ JSON.stringify(response));
}
});
Controller Class
#RestController
#RequestMapping(value = "/api/v1")
public class LeadSquardController {
#Autowired
LeadSquardService leadSquardService;
#GetMapping("leadsquard/user/emailId")
#ResponseBody
public String getByEmailaddress(#RequestBody Object emailId) {
System.out.println("Email : " + emailId.getClass().getName()); //Testing line
System.out.println("Email : " + emailId); //Testing line
return "";
}
}
Why are you using RequestBody when you are sending it as GET request. I would have used POST instead.
Use #PostMapping for your resource and make a POST ajax call.

Post API doesn't give any react

I am developing an application with using JHipster(Java,Spring Boot,Angular).
I have course and student entities. Students should register courses with clicking register button after they logged in.
I wrote post api and tested it from swagger. IT WORKS FINE.
But when i try to link it to a button with angular1; it gives any react.
My Post API(I test it from swagger it works fine)
#PostMapping("/registercourse/{studentId}/{courseId}")
#Timed
public ResponseEntity<Void> registerCourse(#PathVariable Long studentId,#PathVariable Long courseId) {
log.debug("REST request to register {} Course : {} Student : {}", courseId,studentId);
courseRepository.registerCourse(studentId,courseId);
return ResponseEntity.ok().headers(HeaderUtil.createEntityCreationAlert(ENTITY_NAME, courseId.toString())).build();
}
course.register.states.js
(function() {
'use strict';
angular
.module('mucsApp')
.config(stateConfig);
stateConfig.$inject = ['$stateProvider'];
function stateConfig($stateProvider) {
$stateProvider
.state('course.register', {
parent: 'entity',
url: '/registercourse/:studentid/:courseid',
data: {
authorities: ['ROLE_USER']
},
controller: function($scope, $stateParams) {
$scope.studentid = $stateParams.studentid;
$scope.courseid = $stateParams.courseid;
$http({
method: 'POST',
url: 'http://localhost:8080/' + $scope.studentid + '/' + $scope.courseid,
headers: {
'Content-Type': 'application/json'
}
}).then(function successCallback(response) {
console.log("GREAT");
}, function errorCallback(response) {
console.log(response)
});
}
});
}})();
course.register.service.js
(function() {
'use strict';
angular
.module('mucsApp')
.factory('CourseRegister', CourseRegister);
CourseRegister.$inject = ['$resource'];
function CourseRegister ($resource) {
var resourceUrl = 'api/registercourse/:studentid/:courseid';
return $resource(resourceUrl, {}, {
'query': { method: 'POST', isArray: true},
'save': {
method: 'POST',
transformRequest: function (data) {
var copy = angular.copy(data);
return angular.toJson(copy);
}
}
});
}})();
My html button:
<button type="submit"
ui-sref="course.register({studentid:vm.mystudentid , courseid:course.id})"
class="btn btn-info btn-sm">
<span class="glyphicon glyphicon-eye-open"></span>
<span class="hidden-sm-down">Kaydol</span>
</button>
Your Spring controller is looking for this:
#PostMapping("/registercourse/{studentId}/{courseId}")
Your $http call is posting to this:
url: 'http://localhost:8080/' + $scope.studentid + '/' + $scope.courseid
You need to change your call to:
url: 'http://localhost:8080/registercourse' + $scope.studentid + '/' + $scope.courseid
Also, your Controller is not actually using your CourseRegister. you need to inject that in your AngularJS controller if you want to use it.: controller: function($scope, $stateParams,CourseRegister).
My two cents is that in your case, you are better of just using $http. I would put the [updated] $http call into your CourseRegister service, and use that. $resource would require more modifications than I think is worth it.
More on $resource is here.

Ajax and Java web service strange error

I got a really weird error. I successfully run my code and consume the web service. The service return 200 code. But jquery ajax executes error function instead of success. I post the information (Nothing on console):
Javascript:
$(document).ready(
function () {
$.ajax({
url: 'Test/Service/hello',
dataType: 'json',
contentType: 'application/json',
data: {name: 'testing'},
error: function () {
$('#text').html('<p>An error has occurred</p>');
},
success: function (data) {
$("#text").html(data.d);
},
type: 'POST'
});
});
Java:
package com.morethansimplycode.webservice;
import javax.jws.WebParam;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.MediaType;
#Path("/Service")
public class Service {
public Service() {
}
#POST
#Path("/hello")
#Consumes({MediaType.APPLICATION_JSON})
#Produces(MediaType.APPLICATION_JSON)
public String hello(#WebParam(name = "name") String txt) {
return "Hello " + txt + " !";
}
}
Chrome info:
Remote Address:[::1]:8080
Request URL:http://localhost:8080/WebService/Test/Service/hello
Request Method:POST
Status Code:200 OK
Response Headers
view source
Content-Length:17
Content-Type:application/json
Date:Tue, 01 Dec 2015 21:24:26 GMT
Server:GlassFish Server Open Source Edition 4.1
X-Powered-By:Servlet/3.1 JSP/2.3 (GlassFish Server Open Source Edition 4.1 Java/Oracle Corporation/1.8)
Request Headers
view source
Accept:application/json, text/javascript, */*; q=0.01
Accept-Encoding:gzip, deflate
Accept-Language:es-ES,es;q=0.8,ca;q=0.6,en;q=0.4,pt;q=0.2,ru;q=0.2
Cache-Control:no-cache
Connection:keep-alive
Content-Length:9
Content-Type:application/json
Host:localhost:8080
Origin:http://localhost:8080
Pragma:no-cache
Referer:http://localhost:8080/WebService/
User-Agent:Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/46.0.2490.86 Safari/537.36
X-Requested-With:XMLHttpRequest
Request Payload
name=paco
Preview:
Hello name=testing !
What's happening?
Edit 1:
Works with this call:
$(document).ready(
function () {
$.ajax({
url: 'Test/Service/hello',
dataType: 'text',
contentType: 'application/json',
data: {name: 'paco'},
error: function () {
$('#etiqueta').html('An error has occurred');
},
success: function (data) {
console.debug(data);
$("#etiqueta").html('<p>' + data + '</p>');
},
type: 'POST'
});
}
);
But i don't know how can i send an object from the Web Service to the JS as Json to use it with data.d, etc...
Edit 2:
Working correctly as follows:
JS:
$(document).ready(
function () {
$.ajax({
url: 'Test/Service/hello',
dataType: 'json',
contentType: 'application/json',
data: {name: 'paco'},
error: function () {
$('#etiqueta').html('An error has occurred');
},
success: function (data) {
console.debug(data);
$("#etiqueta").html('<p>' + data.d + '</p>');
},
type: 'POST'
});
}
);
Java:
#Path("/Service")
public class Service {
public Service() {
}
/**
* This is a sample web service operation
*
* #param txt
* #return
*/
#POST
#Path("/hello")
#Consumes({MediaType.APPLICATION_JSON})
#Produces(MediaType.APPLICATION_JSON)
public String hello(#WebParam(name = "name") String txt) {
return "{\"d\": \"Hello " + txt + " !\"}";
}
}
Instead of
public String hello(#WebParam(name = "name") String txt) {
return "Hello " + txt + " !";
}
try to use:
public String hello(#WebParam(name = "name") String txt) {
return "{\"d\" : \"Hello " + txt + " !\"}";
}
If you returns some complex class, for example Product, it's converted to json, but if you return String, lib can't convert it to {key=value} and think that you generated json manualy. See this question to more info.

response status from server to client

In my app I want to respond from server to client the status of the operation, for example, from client sends data in format json to server and I want that this responds whit status of the operation, if these data have inserted correctly in database to send status 200,...
I now have this.
Client:
function sendAjax() {
//I build the params necessary to send to server in format json
$.ajax({
url: "/url",
type: 'POST',
dataType: 'json',
data: param,
contentType: 'application/json',
mimeType: 'application/json',
success: function(data) {
alert(data.id );
},
error: function(data,status,er) {
alert("error: "+data+" status: "+status+" er:"+er);
}
});
alert();
}
Server:
Controller.java
#RequestMapping(value = "/", method = RequestMethod.POST)
public #ResponseBody
ResponseJson post (#RequestBody String string){
//I have the operations necessary to insert in database
ResponseJson pruebaJson = new ResponseJson ();
pruebaJson.setId (id);
return pruebaJson;
}
ResponseJson.java
public class ResponseJson implements Serializable
{
private String id;
public String getId ()
{
return id;
}
public void setId (String id)
{
this.id = id;
}
}
How will I process the status that server send to client? this is, if I get status 200 or other status.
My app is realized in spring-mvc and I use javascript with ajax to send data in format json from client to server.
Thanks
You can do it by :
$.ajax({
statusCode: {
404: function() {
alert( "page not found" );
},
200: function() {
alert("insert done..!!!");
},
}
});
This may help you.
See JQuery API for more option.
EDIT : on the basis of my understanding you want to check status code inside success or error function for that
success: function(data , textStatus, jqXHR) {
alert(data.id );
var statusCode = jqXHR.status
if(statusCode == 200 ){
//Your code execute if status is 200
}
}
like wise you can do it in error function also.
In your ajax call success function executes when server sends status 200 code. other than that your error function only executes.
If you want to handle error status separately you can handle in error function with return status.

Categories