Upload file with progress bar on the same page in struts2

0

I need to upload a very heavy file and that's why the progress bar on the same page. I have searched a lot and the interceptor execAndWait does not work for me because it puts the progress bar on an intermediate page. So I developed my own idea, which is this:

uploadNominate.jsp file

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="s" uri="/struts-tags" %>
<%@ taglib prefix="sj" uri="/struts-jquery-tags" %>
<%@ taglib prefix="sb" uri="/struts-bootstrap-tags" %>
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
    <s:head />
    <sj:head jqueryui="true" jquerytheme="cupertino" />
    <sb:head/>
    <link rel="stylesheet" type="text/css" href="vista/css/subirArchivos.css">
    <script type="text/javascript" src="vista/js_libs/bootstrap-filestyle.js"></script>
    <script type="text/javascript" src="vista/js/subirArchivoNomina.js"></script>
    <title><s:property value="%{getText('conciliacion.de.nomina')}"/></title>
</head>
<body>
    <s:form id="form" action="procesarNomina" cssClass="form-horizontal" method="post" enctype="multipart/form-data">
    <div class="row">
        <div class="col-md-4">
            <s:file type="file" class="filestyle" data-buttonBefore="true" id="fileNomina" name="fileNomina" data-text="%{getText('examinar')}" ></s:file>
        </div>
        <div class="col-md-3">
            <sj:progressbar id="progressbarchange" value="21" onChangeTopics="mychangetopic"/> <br /> 
            <sj:a href="#" onClickTopics="myclicktopic" cssClass="buttonlink ui-state-default ui-corner-all">
            <span class="ui-icon ui-icon-refresh"></span>change value</sj:a>
        </div>
    </div>
    <div class="row">
        <div class="col-md-10">
            <s:submit id="btn_subir" button="true" value="%{getText('subir.archivos')}"  class="simple ui-button ui-corner-all ui-widget"   />
        </div>
    </div>
</body>
</html>

uploadNomina.js file

$(document).ready( function(){
    $(":file").filestyle();
    $("#btn_subir").on('click', function(event) {
        event.preventDefault();
        console.log("llegue");
        idInterval=setInterval(function(){
            $.ajax({
                url: "corriendo",
                //data: formData,
                type: "POST",
                processData: false,
                contentType: false
            }).done(function (data, textStatus, jqXHR) {
                console.log(data);//siempre es 0//always is 0
                $("#progressbarchange").progressbar( 'value' , parseInt( data ) );
            }).fail(function (jqXHR, textStatus, errorThrown) {
                //alert("error\njqXHR=" + jqXHR + "\nstatus=" + textStatus + "\nerror=" + errorThrown);
                console.log(jqXHR);
                console.log(textStatus);
                console.log(errorThrown);
            }).always(function(dataORjqXHR, textStatus, jqXHR_ORerrorThrown) {
                //alert( "complete" );
            });
        }, 500*10);
        var formData = new FormData();
        var archivo = document.getElementsByName("fileNomina");
        formData.append("fileNomina", archivo[0].files[0]);
        console.log("action="+$("#form").attr("action"));
        $.ajax({
            url: $("#form").attr("action"),
            data: formData,
            type: "POST",
            processData: false,
            contentType: false
        }).done(function (data, textStatus, jqXHR) {
            clearInterval(idInterval);
            console.log(data);
        }).fail(function (jqXHR, textStatus, errorThrown) {
            alert("error\njqXHR=" + jqXHR + "\nstatus=" + textStatus + "\nerror=" + errorThrown);
        }).always(function(dataORjqXHR, textStatus, jqXHR_ORerrorThrown) {
            //alert( "complete" );
        });
    });
    $.subscribe('mychangetopic', function(event,data){
        console.log("progressbar= "+$("#progressbarchange").progressbar('option', 'value'));
    }); 
    $.subscribe('myclicktopic', function(event,data) {
        $("#progressbarchange").progressbar( 'value' , parseInt( Math.random() * ( 90 ) ) );
    });
});

Here is the main idea: from javascript I execute an action corriendo which will tell me what percentage has been uploaded from the file, so it is in setInterval because it should be executed periodically, then with another ajax I upload the file.

struts.xml

//...
<action name="procesarNomina" class="mx.unam.patronato.conciliacion.actions.SubirNominaAction">
            <interceptor-ref name="fileUpload">
                <param name="maximumSize">52428800</param><!--  50 MB por archivo-->
                <param name="allowedTypes">text/plain, application/rtf, application/msword</param>
            </interceptor-ref>
            <interceptor-ref name="defaultStack"/>
            <result name="success" type="tiles">.subirNominaSinMenu</result>
            <result name="input" type="tiles">.subirNominaSinMenu</result>
        </action>
        <action name="corriendo" class="mx.unam.patronato.conciliacion.actions.SubirNominaAction" method="getStreamPorcentaje">
            <result type="stream">
                <param name="contentType">text/plain</param>
            </result>
        </action>
//...

uploadNominaAction.java

public class SubirNominaAction extends ActionSupport implements SessionAware,ServletRequestAware {
    private SessionMap<String, Object> sessionMap;
    private String fechaInicio,fechaFin;
    private HttpServletRequest request;
    private List<File> fileNomina=new ArrayList<File>();
    private List<String> fileNominaContentType=new ArrayList<String>();
    private List<String> fileNominaFileName=new ArrayList<String>();
    private Double porcentaje;
    private InputStream inputStream;
    public SubirNominaAction() {
        setPorcentaje(0.0);
    }
    //getters y setters
    public String getStreamPorcentaje() {
        inputStream = new ByteArrayInputStream(getPorcentaje().toString().getBytes(StandardCharsets.UTF_8));
        return SUCCESS;
    }
    @Override
    public String execute() throws Exception {
        //System.out.println("entre:"+fechaInicio);
        System.out.print("\n\n---------------------------------------");
        int i=0;
        for (File file : fileNomina){
            double tamanoArchivo=(int)file.length();
            double bytesLine=0;
            int k=0;
            try (Stream<String> lines = Files.lines(Paths.get(file.toURI()), StandardCharsets.ISO_8859_1)){
                for(String line : (Iterable<String>) lines::iterator){
                    bytesLine+=line.getBytes().length;
                    setPorcentaje(bytesLine/tamanoArchivo*100);
                    //System.out.println(getPorcentaje());
                    System.out.println(k+"\t"+line);
                    //System.out.println(line.getBytes().length);
                    k++;
                }
            }catch (Exception e) {
                e.printStackTrace();
            }
            System.out.print("\nFile ["+i+"] ");
            System.out.print("; name:"         + fileNominaFileName.get(i));
            System.out.print("; contentType: " + fileNominaContentType.get(i));
            System.out.print("; length: "      + file.length());
            i++;
        }
        System.out.println("\n---------------------------------------\n");
        return SUCCESS;
    }
}

In uploadNominaAction.java I read the total of the file and then read line by line to calculate the porcentaje that it carries. The file uploads correctly and the percentage is also calculated correctly, I know by console impressions that I made. The problem is that in the setInterval you declare that you invoke the action corriendo and that it in turn invokes getStreamPorcentaje always returns 0 . And that's the value I need to update the progress bar:

console.log(data);//siempre es 0//always is 0
$("#progressbarchange").progressbar( 'value' , parseInt( data ) );

Does anyone have any idea how to correct it? It seems that each time the action class is invoked a new instance is created and it does not use the one that is already running.

    
asked by abrahamhs 04.04.2018 в 20:26
source

0 answers