繁体   English   中英

在带有struts2的同一页面上用进度条上传文件

[英]Upload file with progressbar in the same page with struts2

我需要上传非常重的文件,这就是为什么进度条在同一页面上。 我已经搜索了很多东西,但是execAndWait interceptor器对我不起作用,因为它将进度条放在中间页面上。 因此,我提出了自己的想法,如下所示:

subirArchivoNomina.jsp

<%@ 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>

subirArchivoNomina.js

$(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 ) ) );
    });
});

这里是主要思想:从javascript我执行一个动作corriendo ,它会告诉我从文件上载了什么百分比(porcentaje),这就是为什么它在setInterval原因,因为它必须定期执行,然后使用另一个ajax上传文件。

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>
//...

subirNominaAction.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;
    }
}

subirNominaAction.java我读取了文件的总数,然后subirNominaAction.java读取了该文件percentage(porcentaje) 通过控制台印象,文件可以正确上传并且percentage(porcentaje)也可以正确计算。 问题在于,在 setInterval 中声明它调用动作 corriendo 并依次调用 getStreamPercentaje它始终返回0 这就是我需要更新进度条的值:

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

有谁知道如何纠正它? 似乎每次调用动作类都会创建一个新实例,并且它不会使用已经在运行的实例。

或者在他的缺陷中,有人举了一个例子,说明如何使用interceptor execAndWait与同一页面中的进度interceptor execAndWait一起使用它?

上传进度条与strut无关。 您必须在浏览器端处理更多的JavaScript事情。 通常,struts将在服务器完全接收到完整的上传文件后将其获取。 因此您的方法将始终返回0,因为该文件尚不存在。

使用当前的ajax请求,您仍然可以一次上传文件,并且在上传过程中没有任何反馈。

因此,您需要某种javascript,它可以告诉您有关上传的当前状态。 有像这样的库,甚至还有(一些新的)现代javascript函数(例如XMLHttpRequest高级功能)都可以为您提供帮助。 甚至可以对您希望上传的文件( jquery plugin )进行分块,但是我从未用struts对此进行过测试。

希望这些链接能对您有所帮助。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM