我需要上传一个非常重的文件,这就是为什么同一页面上的进度条。我搜索了很多,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
中,我读取了文件的总数,然后逐行读取以计算所需的percentage(porcentaje)
。该文件正确上传,percentage(porcentaje)
也正确计算,我知道我所做的控制台印象。 问题在于 setInterval
声明它会调用 corriendo
并且反过来调用 getStreamPercentaje
,始终返回0 。这就是我更新进度条所需的价值:
console.log(data);//siempre es 0//always is 0
$("#progressbarchange").progressbar( 'value' , parseInt( data ) );
有谁知道如何纠正它?似乎每次调用action类时都会创建一个新实例,并且它不会使用已经运行的实例。
或者在他的缺陷中,某人有一些关于如何使用interceptor execAndWait
在同一页面中使用进度条的示例?
答案 0 :(得分:0)
上传进度条与struts无关。它更像是你必须在浏览器端处理的javascript。通常struts会在服务器完全接收到之后获得完整的上传文件。因此,您的方法将始终返回0,因为该文件尚不存在。
根据您当前的ajax请求,您仍然可以立即上传文件,并且在上传过程中您不会收到任何反馈。
所以,你需要某种javascript,它可以告诉你上传的当前状态。有像this或甚至(新的现代)javascript函数的库,如XMLHttpRequest advanced features可以帮助你。甚至可以对要上传的文件进行分块(jquery plugin),但我从未使用struts对其进行过测试。
希望链接可以帮助你。