Create inputs for images dynamically and move to Servlet without redirecting the page?

Asked

Viewed 566 times

5

I would like to create a button that brings up a input for sending images.

This button can be used multiple times. When the user(a) click the Submit, these images should be sent to the server without reloading the page.

I want the user to click add field, then an HTML input for images would appear. When he put all the images, and the button Submit would send these images to the Servlet, updating the information on the screen, without redirecting the page.

I tried to use

<jsp:setProperty property="currentImages" name="message" value="${paramValues.campo}" /> 

and the action of Submit back to the page, but this value is always saved. I saw on the Internet that can be done with AJAX, but so far I could not get this vector and pass to Servlet.

How could I do that?

1 answer

4

Manual implementation

You can add multiple upload buttons on the page by adding elements in one div container. Example:

$('#container').append('<input type="file" />');

Then at the time of sending you put everything in an object of type FormData. Example:

var formData = new FormData();
formData.append('imagem', file, file.name);

Finally sends everything via AJAX using XMLHttpRequest. Example:

var xhr = new XMLHttpRequest();
...
xhr.send(formData);

See a full example:

$('#adicionar').on('click', function() {
  $('#container').append('<input type="file" />');
});

$('#enviar').on('click', function() {
  var formData = new FormData();
  $('#container input').each(function() {
    formData.append('imagens[]', this, this.name);
  });
  var xhr = new XMLHttpRequest();
  xhr.open('POST', '/uploadServlet', true);
  xhr.onload = function() {
    if (xhr.status === 200) {
      alert('Sucesso!');
    } else {
      alert('Erro!');
    }
  };
  xhr.send(formData);
});
input {
  display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button id="adicionar">+</button> <button id="enviar">enviar</button>
<div id="container"></div>

Using a plugin

The above code is very simple and works in the most modern browsers.

However, if you want to avoid entering into many implementation details that this could result in a real system ranging from formatting to support older browsers, I suggest using a plugin for this.

A plugin I’ve used successfully in the past was the Blueimp jQuery File Upload.

You can find several examples in the documentation, although in practice this may even hinder a little because it has so many ways to use that you end up spending a good time learning about the plugin.

However, a very simple use can be something like this:

$('#fileupload').fileupload({
    dataType: 'json',
    add: function (e, data) {
        data.context = $('<button/>').text('Upload')
            .appendTo(document.body)
            .click(function () {
                data.context = $('<p/>').text('Uploading...').replaceAll($(this));
                data.submit();
            });
    },
    done: function (e, data) {
        data.context.text('Upload finished.');
    }
});

Servlet

To receive the upload to your Servlet, I suggest using the library Apache Commmons Fileupload.

Understand that from the server’s point of view uploads are complex to manage. Library documentation gives countless examples control you can have.

A simpler case would be like this:

DiskFileItemFactory factory = new DiskFileItemFactory();
ServletFileUpload upload = new ServletFileUpload(factory);
List<FileItem> items = upload.parseRequest(request);
for (FileItem item : itens) {
    if (!item.isFormField()) {
        String fileName = item.getName();
        String contentType = item.getContentType();
        File uploadedFile = new File(...);
        item.write(uploadedFile);
    } else {
        //campos normais
        String campo = item.getFieldName();
        String valor = item.getString();
    }
}

Note that you cannot access the other fields using request.getParameter() and related methods, as the body of a request where occur uploads is different and the server will not decode the fields in the same way as a normal request.

Therefore, as in the example above, you should check the other request fields in the same list of items where the files are. When it’s a normal field, item.isFormField() will be true.

For a more complete description, see this response from the OS (in English).

  • I get it. It worked by passing the values to Servlet via Ubmit. But you still can’t pass the values with the script you passed. When you say, "The code I posted picks up all inputs inside the container," would it be: <div #container input> <input name="files[]" type=file Multiple /> </div> ? @utluiz

  • @Thiagor. Yes, yes. The script I made picks up any tag <input> (independent of the content) that is inside an element with id="conteiner", in this case the div. What is not working? If you look at your browser’s Developer Tool, can you see the AJAX request being sent in the "Network"/"Network" tab? I tested this code on my Chrome and the request is sent. If the request is made but the error occurs on the server, it may be that some header is missing in AJAX. You can then compare the request data with Submit from the request with AJAX.

  • If you continue to face problems, I suggest you create another question and post the code you have that doesn’t work. Here in the comments is not a nice place to get into prolonged discussions.

  • The problem is that the values are always null

Browser other questions tagged

You are not signed in. Login or sign up in order to post.