I am having a problem uploading picture in Spring. I have encountered countless problems, which i have tried to solve. For my current error i have tried all the solution provide by spring but it still persist. According to spring the issue of MissingServletRequestPartException can be solved by including a MultipartResolver.`http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/web/multipart/support/MissingServletRequestPartException.html. I have done that (find below), but the issue still persist.
Error
timestamp: 1490599131962, status: 400, error: "Bad Request",…}
error:"Bad Request"
exception:"org.springframework.web.multipart.support.MissingServletRequestPartException"
message:"Required request part 'uploadfile' is not present"
path:"/uploadFile"
Config
#Bean(name = "multipartResolver")
public CommonsMultipartResolver multipartResolver() {
CommonsMultipartResolver multipartResolver = new CommonsMultipartResolver();
multipartResolver.setMaxUploadSize(100000);
return new CommonsMultipartResolver();
}
Controller
public ResponseEntity<?> uploadFile(#RequestParam("uploadfile") MultipartFile uploadfile, Picture picture, Principal principal, MultipartHttpServletRequest request) {
User user = (User) ((UsernamePasswordAuthenticationToken) principal).getPrincipal();
picture.setUser(user);
Iterator<String> itrator = request.getFileNames();
MultipartFile multiFile = request.getFile(itrator.next());
try {
System.out.println("File Length:" + multiFile.getBytes().length);
System.out.println("File Type:" + multiFile.getContentType());
// Crop the image (uploadfile is an object of type MultipartFile)
BufferedImage croppedImage = cropImageSquare(multiFile.getBytes());
String fileName=multiFile.getOriginalFilename();
System.out.println("File Name:" +fileName);
String path=request.getServletContext().getRealPath("/");
// Get the filename and build the local file path
File directory= new File(path+ "/uploads");
directory.mkdirs();
String filename = uploadfile.getOriginalFilename();
String ext = FilenameUtils.getExtension(filename);
File outPutFile = new File(directory.getAbsolutePath()+System.getProperty("file.separator")+picture.getUploadfile());
ImageIO.write(croppedImage, ext, outPutFile);
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
pictureService.save(picture, uploadfile);
return new ResponseEntity<>(HttpStatus.ACCEPTED);
}
JS FILE
'use strict';
var $formUploader = $("#upload-file-input");
$formUploader.on("submit", function(e){
e.preventDefault();
var data = new FormData(this);
$.each($formUploader.serializeArray(), function(i, field) {
data[field.name] = field.value;
});*/
$.ajax({
//dataType: 'json',
url: $formUploader.prop('action'),
type: "POST",
//data: new FormData($("#upload-file-input")[0]),
data: data,
enctype: 'multipart/form-data',
processData: false,
contentType: false,
cache: false,
success: function (data) {
console.log(data);
// Handle upload success
$("#upload-file-message").text("File succesfully uploaded");
},
error: function (response) {
console.log(response);
// Handle upload error
$("#upload-file-message").text("File not uploaded (File might be big, size needed.)");
}
});
});
Form
<form id="upload-file-input" th:action="#{/uploadFile}" method="post" th:object="${picture}"
enctype="multipart/form-data" class="form-inline inline new-item">
<div th:replace="common/layout :: flash"></div>
<fieldset>
<legend> Upload Picture</legend>
<div class="row">
<div class="col s12 l8">
<div class="file-wrapper">
<input type="file" id="file" name="uploadfile" />
<span class="placeholder" data-placeholder="Choose an image...">Choose an image...</span>
<label for="file" class="button">Browse</label>
<span id="upload-file-message"></span>
</div>
</div>
<button type="submit" class="btn btn-primary">Upload</button>
</div>
</fieldset>
<div class="style16"></div>
</form>
You added all form values into the FormData, but didn't add a content of file. That's how it can be done:
...
var data = new FormData(this);
$.each($formUploader.serializeArray(), function(i, field) {
data[field.name] = field.value;
});
//next line will add content of file
data.append('fileContent', $('#file').files[0]);
$.ajax({ ...
You can use any name instead of fileContent, it doesn't matter.
In case when user enables to select multiple files at once, you have to add contents of all of this files:
...
var data = new FormData(this);
$.each($formUploader.serializeArray(), function(i, field) {
data[field.name] = field.value;
});
$.each($('#file').files, function(i, file) {
formData.append('fileContent' + i, file);
});
$.ajax({ ...
Related
I want to upload picture in database and every time i make ajax call it enters both success and error block.
This is my html:
<div>
<form id="test-form" enctype="multipart/form-data">
<div>
<label>Photos: </label>
<input type="file" id="file"/>
</div>
<input type="button" value="Add" id="add-movie-tvShow-btn">
</form>
</div>
This my ajax call
let insertButton = $("#add-movie-tvShow-btn");
insertButton.on('click', function () {
let formData = new FormData();
let file = $("#file")[0].files[0];
formData.append("file", file);
$.ajax({
url: "http://localhost:8080/upload",
method: "POST",
data: formData,
contentType: false,
processData: false,
success: function(){
alert("Enter success block");
},
error: function(){
alert("Enter error block")
}
});
});
And this is method that process ajax request:
#PostMapping(value = "/upload", consumes = "multipart/form-data")
public void uploadFile(#RequestParam("file") MultipartFile file, Movie movie) throws
IOException {
File convertFile = new File("C:\\Users\\myName\\Desktop\\" + file.getOriginalFilename());
convertFile.createNewFile();
FileOutputStream fout = new FileOutputStream(convertFile);
fout.write(file.getBytes());
movie.setImage(file.getBytes());
movieRepo.save(movie);
fout.close();
}
It creates data in database but i don't understand why enters error block? What did i do wrong?
Can you try preventDefault()? Something like the below.
insertButton.on('click', function (e) {
e.preventDefault();
I'm trying to delete multiple Items with the same name in my web app. But it's giving me an error 500 when I do the POST.
This is my Form Code
<form method="POST" name="deleteFormAdd" id="deleteFormAdd" enctype="multipart/form-data">
<input type="hidden" name="_csrf" th:value="${_csrf.token}" />
<!--Asset ID set to hidden so the User can't see it-->
<input type="hidden" th:each="deleteCategory, itemStat : ${DeleteCategoryObject}"
th:name="assetID"
th:value="${deleteCategory.assetID}"/>
<!-- For showing all the Asset to be deleted -->
<input class="w3-input w3-border w3-round-large" type="text"
th:each="deleteCategory, itemStat : ${DeleteCategoryObject}"
th:name="${DeleteCategoryObject[__${itemStat.index}__].assetType}"
th:value="${deleteCategory.assetType}"
disabled="disabled"/>
<br></br>
<input type="button" class="btn btn-primary btn-block" value="Yes" th:onclick="'javascript:submitForm(\'deleteFormAdd\',\''+#{/delete-asset}+'\')'" />
<button type="reset" onclick="window.location.href = 'manage-assets.html';" class="btn btn-default btn-block"> Cancel</button>
</form>
Submit Form Ajax
function submitForm(formID, url){
var formData = new FormData($("#" + formID)[0]);
$.ajax({
dataType: 'json',
url: url,
data : formData,
type : "POST",
enctype : "multipart/form-data" ,
processData : false,
contentType : false,
success : function(data) {
if (data.status == 1) {
openAlertDialog("Success", "The Asset type has been deleted!", "Continue", "manage-assets");
} else {
openAlertDialog("Error", data.message, "Continue", "manage-assets");
}
},
error : function(data) {
openAlertDialog("Error", data.message, "Continue", "manage-assets");
},
});
}
Spring Controller
#RequestMapping(value = "/delete-asset", method = RequestMethod.POST)
public #ResponseBody String deleteAsset(#ModelAttribute List<AssetCategory> assetCategories) {
JsonObject result = new JsonObject();
if (assetCategories != null && !assetCategories.isEmpty()) {
String[] arr = new String[assetCategories.size()];
for (int i =0; i < assetCategories.size(); i++) {
arr[i] = assetCategories.get(i).getAssetID();
}
assetService.deleteAssets(arr);
result.addProperty("result", "Success");
result.addProperty("status", 1);
result.addProperty("message", "Asset Deleted!");
}
return result.toString();
}
Spring Service
#Override
public AssetCategory deleteAssets(String[] assetID) {
return dao.deleteAssets(assetID);
}
Spring DAO
#Query("Delete From AssetCategory A WHERE A.assetID IN (:assetID)")
public AssetCategory deleteAssets(#Param("assetID") String[] assetID);
Spring Console Error
Failed to instantiate [java.util.List]: Specified class is an interface] with root cause
org.springframework.beans.BeanInstantiationException: Failed to instantiate [java.util.List]: Specified class is an interface
This is the Form Data (it contains the asset ID's)
Seems issue with your ajax function. Check with below:
function submitForm(formID, url) {
var assetIdList = [];
var assetIdObj;
$("#" + formID).find('input[name="assetID"]').each(function () {
assetIdObj = {};
assetIdObj.assetID = $(this).val();
assetIdList.push(assetIdObj);
});
$.ajax({
dataType: 'json',
url: url,
data: {assetCategories: assetIdList},
type: "POST",
enctype: "multipart/form-data",
processData: false,
contentType: false,
success: function (data) {
if (data.status === 1) {
openAlertDialog("Success", "The Asset type has been deleted!", "Continue", "manage-assets");
} else {
openAlertDialog("Error", data.message, "Continue", "manage-assets");
}
},
error: function (data) {
openAlertDialog("Error", data.message, "Continue", "manage-assets");
},
});
}
Update this html code from:
<input type="hidden" th:each="deleteCategory, itemStat : ${DeleteCategoryObject}"
th:name="assetID"
th:value="${deleteCategory.assetID}"/>
To this:
<input type="hidden" th:each="deleteCategory, itemStat : ${DeleteCategoryObject}"
name="assetID"
th:value="${deleteCategory.assetID}"/>
You are using multipart/form-data. So, your request header has multipart/form-data Content-Type which have data as form type. like key=value.
So just remove #ModelAttribute annotation and add consumes properties to your mapping annotation.
//if you're using spring version more than 4.3, use below #PostMapping for readability
//#PostMapping(value = "/delete-asset", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
#RequestMapping(value = "/delete-asset", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
public #ResponseBody String deleteAsset(List<AssetCategory> assetCategories) {
JsonObject result = new JsonObject();
//you can use apache's commons-collection
if (CollectionUtils.isNotEmpty(assetCategories)) {
//and you can also use stream api
String[] arr = assetCategories.stream()
.map(AssetCategory::getAssetID)
.toArray();
assetService.deleteAssets(arr);
result.addProperty("result", "Success");
result.addProperty("status", 1);
result.addProperty("message", "Asset Deleted!");
}
return result.toString();
}
I'm creating a JSP/Servlet web application and I'd like to upload a file to a servlet via Ajax. How would I go about doing this? I'm using jQuery.
I've done so far:
<form class="upload-box">
<input type="file" id="file" name="file1" />
<span id="upload-error" class="error" />
<input type="submit" id="upload-button" value="upload" />
</form>
With this jQuery:
$(document).on("#upload-button", "click", function() {
$.ajax({
type: "POST",
url: "/Upload",
async: true,
data: $(".upload-box").serialize(),
contentType: "multipart/form-data",
processData: false,
success: function(msg) {
alert("File has been uploaded successfully");
},
error:function(msg) {
$("#upload-error").html("Couldn't upload file");
}
});
});
However, it doesn't appear to send the file contents.
To the point, as of the current XMLHttpRequest version 1 as used by jQuery, it is not possible to upload files using JavaScript through XMLHttpRequest. The common workaround is to let JavaScript create a hidden <iframe> and submit the form to it instead so that the impression is created that it happens asynchronously. That's also exactly what the majority of the jQuery file upload plugins are doing, such as the jQuery Form plugin (an example).
Assuming that your JSP with the HTML form is rewritten in such way so that it's not broken when the client has JavaScript disabled (as you have now...), like below:
<form id="upload-form" class="upload-box" action="/Upload" method="post" enctype="multipart/form-data">
<input type="file" id="file" name="file1" />
<span id="upload-error" class="error">${uploadError}</span>
<input type="submit" id="upload-button" value="upload" />
</form>
Then it's, with the help of the jQuery Form plugin, just a matter of
<script src="jquery.js"></script>
<script src="jquery.form.js"></script>
<script>
$(function() {
$('#upload-form').ajaxForm({
success: function(msg) {
alert("File has been uploaded successfully");
},
error: function(msg) {
$("#upload-error").text("Couldn't upload file");
}
});
});
</script>
As to the servlet side, no special stuff needs to be done here. Just implement it exactly the same way as you would do when not using Ajax: How can I upload files to a server using JSP/Servlet?
You'll only need an additional check in the servlet if the X-Requested-With header equals XMLHttpRequest or not, so that you know how what kind of response to return for the case that the client has JavaScript disabled (as of now, it is mostly the older mobile browsers which have JavaScript disabled).
if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) {
// Return an Ajax response (e.g. write JSON or XML).
} else {
// Return a regular response (e.g. forward to JSP).
}
Note that the relatively new XMLHttpRequest version 2 is capable of sending a selected file using the new File and FormData APIs. See also HTML5 drag and drop file upload to Java Servlet and Send a file as multipart through XMLHttpRequest.
Monsif's code works well if the form has only file type inputs. If there are some other inputs other than the file type, then they get lost. So, instead of copying each form data and appending them to FormData object, the original form itself can be given to the constructor.
<script type="text/javascript">
var files = null; // when files input changes this will be initialised.
$(function() {
$('#form2Submit').on('submit', uploadFile);
});
function uploadFile(event) {
event.stopPropagation();
event.preventDefault();
//var files = files;
var form = document.getElementById('form2Submit');
var data = new FormData(form);
postFilesData(data);
}
function postFilesData(data) {
$.ajax({
url : 'yourUrl',
type : 'POST',
data : data,
cache : false,
dataType : 'json',
processData : false,
contentType : false,
success : function(data, textStatus, jqXHR) {
alert(data);
},
error : function(jqXHR, textStatus, errorThrown) {
alert('ERRORS: ' + textStatus);
}
});
}
</script>
The HTML code can be something like following:
<form id ="form2Submit" action="yourUrl">
First name:<br>
<input type="text" name="firstname" value="Mickey">
<br>
Last name:<br>
<input type="text" name="lastname" value="Mouse">
<br>
<input id="fileSelect" name="fileSelect[]" type="file" multiple accept=".xml,txt">
<br>
<input type="submit" value="Submit">
</form>
$('#fileUploader').on('change', uploadFile);
function uploadFile(event)
{
event.stopPropagation();
event.preventDefault();
var files = event.target.files;
var data = new FormData();
$.each(files, function(key, value)
{
data.append(key, value);
});
postFilesData(data);
}
function postFilesData(data)
{
$.ajax({
url: 'yourUrl',
type: 'POST',
data: data,
cache: false,
dataType: 'json',
processData: false,
contentType: false,
success: function(data, textStatus, jqXHR)
{
//success
},
error: function(jqXHR, textStatus, errorThrown)
{
console.log('ERRORS: ' + textStatus);
}
});
}
<form method="POST" enctype="multipart/form-data">
<input type="file" name="file" id="fileUploader"/>
</form>
This code works for me.
I used Commons IO's io.jar, Commons file upload.jar, and the jQuery form plugin:
<script>
$(function() {
$('#upload-form').ajaxForm({
success: function(msg) {
alert("File has been uploaded successfully");
},
error: function(msg) {
$("#upload-error").text("Couldn't upload file");
}
});
});
</script>
<form id="upload-form" class="upload-box" action="upload" method="POST" enctype="multipart/form-data">
<input type="file" id="file" name="file1" />
<span id="upload-error" class="error">${uploadError}</span>
<input type="submit" id="upload-button" value="upload" />
</form>
boolean isMultipart = ServletFileUpload.isMultipartContent(request);
if (isMultipart) {
// Create a factory for disk-based file items
FileItemFactory factory = new DiskFileItemFactory();
// Create a new file upload handler
ServletFileUpload upload = new ServletFileUpload(factory);
try {
// Parse the request
List items = upload.parseRequest(request);
Iterator iterator = items.iterator();
while (iterator.hasNext()) {
FileItem item = (FileItem) iterator.next();
if (!item.isFormField()) {
String fileName = item.getName();
String root = getServletContext().getRealPath("/");
File path = new File(root + "../../web/Images/uploads");
if (!path.exists()) {
boolean status = path.mkdirs();
}
File uploadedFile = new File(path + "/" + fileName);
System.out.println(uploadedFile.getAbsolutePath());
item.write(uploadedFile);
}
}
} catch (FileUploadException e) {
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
}
I am able to upload file just fine, I just would like to prevent redirecting. That is obviously done by AJAX form submit, but I still end up in the controller which then redirects me.
My Controller:
#RequestMapping(method=RequestMethod.POST)
public void handleFileUpload(#RequestParam("name") String name,
#RequestParam("file") MultipartFile file){
if (!file.isEmpty()) {
try {
byte[] bytes = file.getBytes();
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(name)));
stream.write(bytes);
stream.close();
//return new ModelAndView("redirect:register");
} catch (Exception e) {
//return new ModelAndView("redirect:register");
}
} else {
//return new ModelAndView("redirect:register");
}
}
JSP part:
<script>
$('fileUploadForm').submit(function (e) {
$.ajax({
url: '${home}upload',
data: $('fileUploadForm').serialize(),
processData: false,
type: 'POST',
success: function (data) {
alert(data);
}
});
e.preventDefault();
});
</script>
<form id ="fileUploadForm" method="POST" action="upload?${_csrf.parameterName}=${_csrf.token}" enctype="multipart/form-data">
File to upload: <input type="file" name="file">
Name:
<input type="text" name="name">
<input type="submit" value="Upload"> Press here to upload the file!
</form>
If your controller is not Restfull then you need to indicate to the method that its a restfull call.
Try the below fix.
#RequestMapping(method=RequestMethod.POST)
#ResponseBody // add this
public void handleFileUpload(#RequestParam("name") String name, #RequestParam("file") MultipartFile file) {}
Hi I'm trying to upload a image file to the server.I have used jCrop to crop the image before uploading and used canvas to get the cropped image coordinates.I have included controller and jsp files .But I'm not able to send formdata using ajax.
AppController.java
#RequestMapping(value = "/upload", method = RequestMethod.POST)
public String handleFormUpload(#RequestParam("file") MultipartFile file, ModelMap model) throws IOException{
if (!file.isEmpty()) {
Authentication auth = SecurityContextHolder.getContext().getAuthentication();
String name = auth.getName(); //get logged in username
BufferedImage src = ImageIO.read(new ByteArrayInputStream(file.getBytes()));
File destination = new File("/home/me/Desktop/"+name+".png");
model.addAttribute("username", name);
// something like C:/Users/tom/Documents/nameBasedOnSomeId.png
ImageIO.write(src, "png", destination);
//Save the id you have used to create the file name in the DB. You can retrieve the image in future with the ID.
}else {
System.out.println("file is empty");
}
return "prefs";
}
prefs.jsp
<script type="text/javascript">
$(function(){
$('.majorpoints').click(function(){
$(this).find('.hiders').slideToggle();
});
$("#imgInp").change(function(){
var c = $('.cropArea').Jcrop({
onSelect: updateCoords,
bgOpacity: .4,
setSelect: [ 100, 100, 50, 50 ],
aspectRatio: 16 / 9
});
function readURL(input) {
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function (e) {
$('#blah').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
}
readURL(this);
});
$('#btnCrop').click(function () {
var x1 = $('#x').val();
var y1 = $('#y').val();
var width = $('#w').val();
var height = $('#h').val();
var canvas = $("#canvas")[0];
alert(x1+""+y1+""+""+width+""+height);
var context = canvas.getContext('2d');
var img = new Image();
img.onload = function () {
canvas.height = height;
canvas.width = width;
context.drawImage(img, x1, y1, width, height, 0, 0, width, height);
$("#imgInp").val(canvas.toDataURL("image/jpeg"));
};
var data = new FormData();
data.append('file', dataURItoBlob(canvas.toDataURL("image/jpeg")));
$.ajax({
url: 'upload',
data: data,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
img.src = $('#blah').attr('src');
});
});
function dataURItoBlob(dataURI) {
// convert base64/URLEncoded data component to raw binary data held in a string
var byteString;
if (dataURI.split(',')[0].indexOf('base64') >= 0)
byteString = atob(dataURI.split(',')[1]);
else
byteString = unescape(dataURI.split(',')[1]);
// separate out the mime component
var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
// write the bytes of the string to a typed array
var ia = new Uint8Array(byteString.length);
for (var i = 0; i < byteString.length; i++) {
ia[i] = byteString.charCodeAt(i);
}
return new Blob([ia], {type:mimeString});
}
function updateCoords(c)
{
console.log(c);
$('#x').val(c.x);
$('#y').val(c.y);
$('#w').val(c.w);
$('#h').val(c.h);
$('#btnCrop').show();
};
</script>
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<form method="POST" action="upload" enctype="multipart/form-data">
Please select a file to upload :
<input type="file" name="file" class="file" id="imgInp" />
<div class="cropArea">
<img id="blah" src="#" alt="your image" />
</div>
<input type="hidden" id="x" name="x" />
<input type="hidden" id="y" name="y" />
<input type="hidden" id="w" name="w" />
<input type="hidden" id="h" name="h" />
<canvas id="canvas" height="5" width="5"></canvas>
</form>
<input type="button" id="btnCrop" value="Crop" style="display: none" />
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
You are missing this param
enctype: 'multipart/form-data'
$.ajax({
url: 'upload',
data: data,
contentType: false,
processData: false,
enctype: 'multipart/form-data',
type: 'POST',
success: function(data){
alert(data);
}
});
You should have this
var data = new FormData();
data.append('file', jQuery('#imgInp')[0].files[0]);
instead of
jQuery.each(jQuery('#imgInp')[0].files, function(i,file) {
data.append('file-'+i, file);
});
Later Edit 2:
in your function dataURItoBlob(dataURI) add callback like this:
function dataURItoBlob(dataURI, callback) {
...
callback();
}
then in
$('#btnCrop').click(function () { ...
data.append('file', dataURItoBlob(canvas.toDataURL("image/jpeg", function(){
$.ajax({
url: 'upload',
data: data,
contentType: false,
processData: false,
type: 'POST',
success: function(data){
alert(data);
}
});
})));
this way, you are sure that you make the ajax call after dataURItoBlob is executed.