0

I've created a custom MultipartFilter for a HttpServletRequest using this example to upload any kind of files from the client to my DataBase.

The form is a multipart/form-data form placed inside a modal, shown in other form :

<!-- MAIN FORM -->
<form:form>
    <button // this button shows the modal
</form:form>

<!-- MODAL TO UPLOAD FILES -->
<div class="modal fade" id="myModal" data-backdrop="static" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="false">
    <form action="documentoSubmit" method="post" id="documentoForm" enctype="multipart/form-data">

I can submit my form and find the filed and other fields correct via my custom Filter in two ways:

a) Button onchange method and javascript function:

<button type="button" class="btn btn-primary" onclick="validarDocumento()">
    <spring:message code="guardar" />
</button>

function validarDocumento() {
    // check if valid data
    $("#myform").submit();
}

b) Input field (can be also a <button>):

<input type="submit" class="btn btn-default" >

This is working correct, but my problem is the parent form, which contains the modal with the form is being reloaded , I need to catch result to update my view via AJAX WITHOUT reloading the form.

Anything similar to this, but with my custom java Filter being applied

$.post( "<%=session.getAttribute("URL_HOST")%>/my/url/documentoSubmit", {})
.done(function(data) {
    // do stuff...
}

or

$("#myForm").submit().done(function (data){
    // do stuff...
});

or

$("#myForm").submit(function (data){
    // do stuff...
});
Jordi Castilla
  • 26,609
  • 8
  • 70
  • 109
  • Not exaclty duplicate, but please check older related question: http://stackoverflow.com/questions/17934689/can-someone-explain-how-to-implement-the-jquery-file-upload-plugin – ikettu Jan 19 '15 at 10:36
  • Hi, if you want to update your view using ajax without reloading, you must not use the method submit or to make an input of type submit, because the submit reload the page no matter what you do, i advice you to work with an input type button or using the click function. I hope that i helped you. – marsahllDTitch Jan 19 '15 at 10:41
  • @mehdizahrane I know that, It's in the question, the problem when I submit the form is the customized Filter is not being used, so data is not passed to server in correct way – Jordi Castilla Jan 19 '15 at 10:51
  • @ikettu similar, but not exactly related. That's `PHP` and I need to use a `Java` Filter.... – Jordi Castilla Jan 19 '15 at 10:59
  • If you have Java filter in place, it's more problem how to post data as multipart content to that filter? Maybe you can use JS parts from link I gave. – ikettu Jan 19 '15 at 11:04
  • i've tried js submit before filter, this worked for me but only for some kind of files(images, docs...), and i need to upload any file... :( – Jordi Castilla Jan 19 '15 at 11:15
  • The example you are following is from 2007. And there is a note at the top mentioning newer ways. It also looks too complicated for just trying to filter out filetypes. But I don't work with Java servers so I could be missing something. – DanielST Jan 21 '15 at 21:33

3 Answers3

2

You can try approach with iframes. Make fake frame that is hidden and callback for iframe loaded.

<form action="youAction" method="post" id="documentoForm" target = "fake-frame" enctype="multipart/form-data"></form>
<iframe id="fake-frame" name="fake-frame" style="display: none"></iframe>

And a callback:

iframe.load(function () {
/*you may pass some special content to detect file loaded { status = "success" }*/
}
Dmitriy Krupin
  • 591
  • 3
  • 6
2

The problem with your code is in this function

function validarDocumento() {
    // check if valid data
    $("#myform").submit();
}

Calling submit() on jquery element will actually submit the form, which is a synchronous request, hence the page is refreshed. To prevent that, you have to upload your files via AJAX, don't worry your Custom Filter will still work as it basically intercepts every incoming request (synchronous/asynchronous doesn't matter) to your server.

If you wan't to use JQuery, you can do something like this

<input type="file" id="uploadfile" name="uploadfile" />

$('.btn btn-primary').on('submit', function(event){
    event.stopPropagation(); // Stop propagating submit event to your parent form
    event.preventDefault(); // Stop form's default action in your modal

    var data = new FormData();
    var file = document.getElementById("uploadfile");
    formData.append("upload", file.files[0]);
    // append other form fields to formData

         $.ajax({
              url: 'ur-action-to-upload-file',
              type: 'POST',
              data: data,
              cache: false,
              dataType: 'json',
              processData: false,
              contentType: 'multipart/form-data' 
         }).done(function(data,jqXHR){
                if(jqXHR.status == 200){
                 // handle your success flow
                }
         });
});

Few things to notice,

  • processData - Set this to false if you have files because jQuery will convert the files arrays into strings and the server can't pick it up.
  • contentType - if multipart/form-data is not working, set this to false but don't leave it because jQuery defaults to application/x-www-form-urlencoded and doesn't send the files

In case you need more examples, refer to this and this

Arkantos
  • 6,530
  • 2
  • 16
  • 36
  • 1
    `contentType` has to be false, overriding it will prevent the browser from setting a boundary which is necessary to interpret the request. – Musa Jan 26 '15 at 19:13
-1

I would suggest using the fileReader, FormData and XMLHTTPRequest API's. example:

// button click to submit
<button type="button" class="btn btn-primary" onclick="validarDocumento()">
//input change
<input name="file" onchange='readFile'>

//global vars
       var data = new FormData(),
       reader - new FileReader(),
       xhr =  new XMLHttpRequest();    
//considering the example, you could validate file and read as binary or a base64 decoded file before upload
function readFile(e){
 file = e.target.files[0]; // reads the file input change event and returns array
 var binaryFile = reader.readAsBinaryString(file); // file reader gets file as binary
 reader.onloadend(function(e){
   //check reader data
   data.append('file', binaryFile);
 });
}
function validarDocumento(){
  // validate document and other inputs
 xhr.upload.onprogress =  function(event){
   // event that checks for progress on upload;
 };
 xhr.onload = function(e){
 // check for server responce on event and refresh view
 };
 xhr.open("POST","<%=session.getAttribute("URL_HOST")%>/my/url/documentoSubmit",true);
 xhr.send(data);
}

although this might need some tweaking to work with you file its a simple example that I hope will point you in the right direction. this helps you submit your form and check through javascript when to refresh your view / perhaps reset your input considering files will remain in the dome since there's no refresh.

also check out the other ways you might be able to read the file to help matching the java server expected data

user1375895
  • 73
  • 1
  • 10
  • 1
    Using a `FileReader` is unnecessary(just append the file itself to the FormData object) and using `readAsBinaryString` like that will give you incorrect results. – Musa Jan 26 '15 at 19:15