File upload is not working in spring using jquery-ajax - spring

This is my form :
<form name="CIMtrek_Compliance_Daily_Shipments" enctype="multipart/form-data">
<input type="file" id="CIMtrek_comments" name="CIMtrek_comments" value="" />
<button id="upload" onclick="uploadCommentFile()">Upload</button>
</form>
and this is my ajax call using jquery :
function uploadCommentFile(){
$("#upload").live("click", function() {
var file_data = $("#CIMtrek_comments").prop("files")[0]; // Getting the properties of file from file field
var form_data = new FormData(); // Creating object of FormData class
form_data.append("file", file_data) // Appending parameter named file with properties of file_field to form_data
//form_data.append("user_id", 123) // Adding extra parameters to form_data
$.ajax({
type: 'POST',
url: "/CIMtrek_Compliance_Daily_Shipments_FileUpload",
dataType: 'script',
cache: false,
contentType: false,
processData: false,
data: {
uploadFile: file_data
},
success: function (msg) {
global.getElementById("CIMtrek_uploadedFileName").innerHTML=msg;
}
})
})
}
and this is my spring controller :
#RequestMapping(value = "/CIMtrek_Compliance_Daily_Shipments_FileUpload", method = RequestMethod.POST)
public String createComments(#RequestParam("uploadFile") CommonsMultipartFile uploadItem,
HttpServletRequest request) {
String uploadedFileName="";
try {
MultipartFile file = uploadItem;
String fileName = null;
InputStream inputStream = null;
OutputStream outputStream = null;
if (file.getSize() > 0) {
inputStream = file.getInputStream();
System.out.println("size::" + file.getSize());
fileName = request.getRealPath("") + "/WEB-INF/resources/Attachment"+ file.getOriginalFilename();
System.out.println("path : "+request.getRealPath("") + "/WEB-INF/resources/Attachment");
outputStream = new FileOutputStream(fileName);
System.out.println("fileName:" + file.getOriginalFilename());
int readBytes = 0;
byte[] buffer = new byte[10000];
while ((readBytes = inputStream.read(buffer, 0, 10000)) != -1) {
outputStream.write(buffer, 0, readBytes);
}
outputStream.close();
inputStream.close();
}
uploadedFileName =file.getOriginalFilename();
} catch (Exception e) {
e.printStackTrace();
}
return uploadedFileName;
}
but i get the following exception when i click on upload button :
HTTP Status 400 -
The request sent by the client was syntactically incorrect.
what could be the problem, Please help me to identify.
Best Regards.

Follow this one it helped and solved my problem :

Related

Sending file object to Spring Rest controller through angular 5

I am trying to upload a file on client side and send HTTP Post request to Spring Rest Controller. But when I receive the file object in Rest controller I could see it as 'null'.
HTML code :
<input type="file" id="myFile" (change) = "onFileChange($event)" #fileInput>
Corresponding .ts file :
onFileChange($event) : void {
let file:File = $event.target.files[0];
let myReader: FileReader = new FileReader();
myReader.onloadend = function(e) {
}
myReader.readAsText(file);
const req = this.http.post('/abc',myReader.result, {
headers: new HttpHeaders().set('content-type','application/pdf')
});
req.subscribe(
(data) => {
console.log(data);
},
(err: HttpErrorResponse) => {
if(err.error instanceof Error) {
//client side error
console.log('An error occured: ',err.error.message);
} else {
console.log('Backend returned code', err.status, 'body was ',err.error);
}
}
)
}
My Spring Rest Controller :
#RequestMapping(value="/abc", method = RequestMethod.POST, consumes = "application/pdf")
public ResponseEntity<String> uploadFile(#RequestBody MultipartFile file) {
System.out.println("Inside Controller");
return new ResponseEntity<>("true", HttpStatus.CREATED);
}
Could anyone please help to find out the issue here.
Try below code
HTML Template
<input type="file" id="myFile" (change)="onFileChange(fileInput.files)" #fileInput>
TypeScript
import { Headers, RequestOptions } from '#angular/http'; // Import header and requestOptions
//On File Select
onFileChange(files: any) {
let file: File = files[0];
let headers = new Headers();
let options = new RequestOptions({ headers: headers }); // Create header
let formData = new FormData();
formData.append('file', file); // Append file to formdata
const req = this.http.post('/abc', formData, options);
req.subscribe( (data) => {
console.log(data); // Sucess response
}, (err: HttpErrorResponse) => {
// Erro response
if(err.error instanceof Error) {
//client side error
console.log('An error occured: ',err.error.message);
}
else {
console.log('Backend returned code', err.status, 'body was ',err.error);
}
})
}
Spring Controller
#RequestMapping(value="/abc", method = RequestMethod.POST)
public ResponseGenerator uploadFile(#RequestParam MultipartFile file) {
ResponseGenerator responseGenerator = new ResponseGenerator();
try {
if (file != null) {
System.out.println(file.getOriginalFilename());
}
return responseGenerator;
} catch (Exception e) {
logger.error("Error while updating user : ", e);
return responseGenerator;
}
}
It will be better way if you create one service and put your http method code in that service. refer this link Angular 2 template form with input type=file and spring boot
the easiest thing to do (according to me) is to use a FormData object.
Here is how :
#viewChild() fileInput: ElementRef;
onFileChange(event) {
const files = this.fileInput.nativeElement.files as FileList;
const file = files.item(0);
const formData = new FormData();
formData.append('pdf', file, file.name);
this.http.post('abc', formData, {
headers: new HttpHeaders().set('content-type','application/pdf')
}).subscribe(
data => console.log(data),
err => console.log(err)
);
}
Try this and tell me what you see on Spring side.

How to retrieve uploaded file using ajax on java server side?

I am using struts2 framework on server side. I am uploading a file using
server side :
<s:file name="fTU" id="fTU"/>
<input type="submit" value ="ok" onclick="upload()">
client side :
function upload(){
var file = document.getElementById("fTU");
try {
this.xml = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
this.xml = new ActiveXObject("Microsoft.XMLHTTP");
} catch (err) {
this.xml = null;
}
}
if(!this.xml && typeof XMLHttpRequest != "undefined")
this.xml = new XMLHttpRequest();
if (!this.xml){
this.failed = true;
}
var formData = new FormData();
/* Add the file */
formData.append("upload", file.files[0]);
xml.open("POST", "", true);
xml.setRequestHeader("Content-Type", "false");
xml.send(formData); /* Send to server */
xml.onreadystatechange = function () {
if (xml.readyState == 4 && xml.status == 200) {
alert(xml.statusText);
}
}
}
How to fetch the uploaded file object on struts2 server side?
It is going in server side class and I am trying to retrieve file by using request.getParameter(upload) but it is giving null.
function upload(form){
var fd = new FormData(form);
$.ajax({
url : "<url-value>", //this is the actionName
type: "POST",
data: fd,
processData: false,
contentType: false,
success: function(data){
},
error: function(xhr, status, error){
var err = eval("(" + xhr.responseText + ")");
alert(err.Message);
}
});
return false;
}
I think you missed to add the Action Link in the xml.open() method. Take a look at the MDN to see some examples.
How does your Action-class look like? Have you defined a File field named upload with getter/setters?
Please also check, that your browser supports the FormData element, see question.
I also would suggest you to use a library like jQuery to simplify the Javascript code.
Action
public class FileUpload extends ActionSupport {
File myFile;
public String execute() {
//do some preparations for the upload
return SUCCESS;
}
public String upload() {
//only here the myFile is filled with data
return SUCCESS;
}
public void setMyFile(File myFile) {
this.myFile = myFile;
}
public File getMyFile() {
return myFile;
}
}
struts.xml
<!-- init method to show the form -->
<action name="fileForm" class="...FileUpload">
<result name="success">fileupload.jsp</result>
</action>
<!-- upload method to upload the file -->
<action name="fileUpload" class="...FileUpload" method="upload">
<result name="success">fileupload.jsp</result>
</action>
JSP
<s:form enctype="multipart/form-data" method="post" name="fileinfo" action="fileUpload">
<s:file name="myFile"/>
</s:form>
<input type="submit" onClick="upload()" value="OK">
Javascript (taken from the MDN example above)
function upload() {
var fd = new FormData(document.querySelector("form"));
$.ajax({
url : "fileUpload", //this is the actionName
type: "POST",
data: fd,
processData: false,
contentType: false
});
return false; //to stop submitting the form
}
I have not tested this code, so please change it or add comments if something doesn't work.

Could not parse multipart servlet request; nested exception is FileUploadException: the request was rejected because no multipart boundary was found

In my current spring-boot project, I have this form to upload a war file to the server:
<form:war>
<div class="field-box">
<label th:text="${war}"></label>
<div class="col-md-7">
<input class="form-control arquivo" th:attr="data-classe=${command['class'].simpleName},target=${war}" th:id="${war}" type="file" />
</div>
</div>
</form:war>
the form is handled by this controller method:
#RequestMapping(value="download", method=RequestMethod.GET)
#ResponseBody
public HttpEntity<byte[]> download(#RequestParam(value="id") String id) throws Exception {
return this.serv.download(id);
}
and by this method in the service class:
public String upload(String id, String classe, String target, MultipartFile file) throws Exception {
Arquivo novo;
if(id == null) {
novo = new Arquivo(classe, target);
this.dao.insert(novo);
id = novo.getId();
} else {
novo = this.dao.findById(id);
}
byte[] bytes = file.getBytes();
File arquivo = new File(novo.toString());
if(!arquivo.exists())
if(arquivo.mkdirs())
arquivo.createNewFile();
BufferedOutputStream stream = new BufferedOutputStream( new FileOutputStream(arquivo) );
stream.write(bytes);
stream.close();
return novo.getId();
}
all this is triggered by this jquery code:
$("input.arquivo").on("change", function(event){
console.log('mudanca no campo de arquivo');
var c = $(this).data('classe');
var t = $(this).data('target');
var f = $(this).val();
$.ajax({
method: "POST",
url: "/Picture/upload",
data: { classe: c, target: t, file: f },
contentType: "multipart/form-data"
}).done(function(data){
console.log('id: '+data);
$(this).attr('type', 'hidden');
$(this).attr('name', t);
$(this).attr('value', data)
});
});
my application.properties have this configuration:
# Multipart Configuration
multipart.location = ${user.home}/.lojacms/Uploads
multipart.maxFileSize = 100Mb
multipart.maxRequestSize = 100Mb
multipart.fileSizeThreshold = 10Mb
but when I try upload a file, I get the error described above (in the title). Anyone can tell me what's wrong here?
Ok, then I found the solution changing the javascript code to this:
$("input.arquivo").on("change", function(event){
var c = $(this).data('classe');
var t = $(this).data('target');
var formData = new FormData();
formData.append('classe', c);
formData.append('target', t);
formData.append('file', $('#input_'+t)[0].files[0]);
$.ajax({
method: "POST",
url: "/Arquivo/upload",
data: formData,
cache: false,
contentType: false,
processData: false
}).done(function(data){
$('#'+t).append('<input type="hidden" name="'+t+'" value="'+data+'"/>')
});
});
In short words, I am using the FormData element of the javascript to handle the values submited to the server, including the multipart data.

File upload using AnguarJS

I wanted to upload image in an AJAX manner and did so with reference to this Article
What I have done:
Controller:
$scope.uploadImage = function () {
var result;
var formdata = new FormData();
var fileInput = document.getElementById('fileInput');
for (var i = 0; i < fileInput.files.length; i++) {
formdata.append(fileInput.files[i].name, fileInput.files[i]);
}
var xhr = new XMLHttpRequest();
xhr.open('POST', '/Common/Image_upload?imageType=' + $scope.imageType);
xhr.send(formdata);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4 && xhr.status == 200) {
alert(xhr.responseText);
}
}
};
View:
<form id="uploader" ng-submit="uploadImage()">
<input id="fileInput" type="file">
<input type="submit" value="Upload file" />
</form>
MVC Controller:
[HttpPost]
public JsonResult Image_upload(string imageType)
{
....
success = ProductImage_insert(Image);
message = success ? "Image uploaded successfully!" : "Image was not uploaded!";
return Json(message, JsonRequestBehavior.AllowGet);
}
Requirement:
I need to catch this JSON response in the controller, how can I do it?
Thanks in advance.
You can do it in a angular way:
$scope.uploadImage = function () {
var fileInput = document.getElementById('fileInput');
var messageHeaders = { 'Content-Type': 'application/x-www-form-urlencoded' };
messageHeaders['X-File-Name'] = encodeURI(fileInput.files[0].name);
messageHeaders['X-File-Type'] = encodeURI(fileInput.files[0].type);
var fileData = fileInput.files[0];
$http({
url: '/Common/Image_upload',
method: "POST",
data: fileData,
headers: messageHeaders
}).success(function (data, status, headers, config) {
// do what you want with the response
});
}
on the server read Request.InputStream for a file content
[HttpPost]
public virtual ActionResult Image_upload(productType)
{
var xfileName = HttpUtility.UrlDecode(Request.Headers["X-File-Name"]);
var xfileType = HttpUtility.UrlDecode(Request.Headers["X-File-Type"]);
var inputStream = Request.InputStream;
var fileLenght = (int)inputStream.Length;
var bytes = new byte[fileLenght];
Request.InputStream.Read(bytes, 0, fileLenght);
System.IO.File.WriteAllBytes(Server.MapPath("/MyFiles/" + xfileName), bytes);
// return status code 200 or any other data
return new HttpStatusCodeResult(200);
}

Sending other data besides File in Ajax Post in Spring MVC

I am trying to send some other data with the file in ajax post
var fileInput = document.getElementById('file');
var creditcardid = document.getElementById('creditcardid');
var file = fileInput.files[0];
var formData = new FormData();
formData.append('creditcardid', 'creditcardid');
formData.append('file', file);
$.ajax({
url: url,
data: formData,
cache: false,
contentType: false,
processData: false,
type: 'POST',
success: function(response) {
document.getElementById('statusMsg').innerHTML="<fmt:message key="fileUpload.success"/>";
Success();
}
In controller i am writing the code as
#RequestMapping(value = "/fileUpload", method = RequestMethod.POST)
public #ResponseBody String fileUpload(#RequestParam(value = "creditcardid")Long creditcardid,#RequestParam(value = "file") MultipartFile file,Model model, HttpServletRequest request) {
String response = "generic.unexpectederror";
try {
model.addAttribute("message", "File '" + file.getOriginalFilename() + "' uploaded successfully");
logger.info("Size of the file is " + file.getSize());
logger.info("Name of the file is " + file.getOriginalFilename());
response = "fileUpload.success";
} catch (DataIntegrityViolationException e) {
response = "fileUpload.error";
logger.error(ExceptionUtils.getStackTrace(e));
}
return response;
}
But my code is not calling controller. Please let me know how to receive both the data and the file. Thanks

Resources