显示"进行中"下载Excel文件时出现错误信息

时间:2015-10-08 14:32:43

标签: excel spring jsp

我正在构建一个Spring MVC应用程序,点击链接,我希望在我的控制器中完成一些处理。 Controller将根据处理生成Excel工作表,并将此Excel工作表发送回相同的JSP。

但是由于控制器处理和下载文件需要一些时间,比如大约30秒,我想显示一个"正在进行中"窗口或用户的某种信息,以便他们清楚地意识到正在进行下载并且用户应该等待。我尝试下面的代码显示了该消息,但没有下载该文件:

function validateMyValues(value1, value2) 
{
    dialog = openWin("Please wait while downloading is in progress....");
    document.myform.action="getDbData";

    var data = 'value1='
                +value1+'&value2='
                +value2; 
    alert("Action1: " + document.myform.action);
    $.ajax({
        type: "POST",
        url: document.myform.action,
        data: data,
        success: closeWin
    }); 
}

var myWindow;

function openWin(message) {
    var w = 200;
    var h = 200;
    var left = Number((screen.width/2)-(w/2));
    var top = Number((screen.height/2)-(h/2));

    myWindow = window.open("", "myWindow", 'width='+w+', height='+h+',   top='+top+', left='+left);
    myWindow.document.write(message);

}

function closeWin() {
   myWindow.close();
}

以下是我的JSP链接:

<a class="myClass1" href="javascript:validateMyValues('<%=value1%>','<%=value2%>')"><img src="./images/btn_valid.png" border="0" /></a>

我的下载控制器代码是:

    //flushing now the file to web page
FileInputStream fileIn = new FileInputStream(outputFile);
ServletOutputStream out = response.getOutputStream();

response.setContentType ("application/download");
response.setHeader ("Content-Disposition", "attachment; filename=\""+filename+"\"");
response.setHeader("Set-Cookie", "fileDownload=true; path=/");

byte[] outputByte = new byte[4096];

//copy binary content to output stream
while(fileIn.read(outputByte, 0, 4096) != -1)
{
    out.write(outputByte, 0, 4096);
}

fileIn.close();
out.flush();
out.close();

return null;

我唯一需要的是显示正在进行的&#34;&#34;向用户发送消息,直到下载完成。

1 个答案:

答案 0 :(得分:0)

如果处理需要一段时间,您的选择是将结果传回客户端。这意味着在数据仍在输出流中写入时发回数据。

为此,您可以使用JDK 7 PipedOutputStream。例如:

PipedOutputStream out = new PipedOutputStream();
PipedInputStream in = new PipedInputStream(out); 

executor.execute(new Runnable() {

    @Override
    public void run() {
        while(fileIn.read(outputByte, 0, 4096) != -1){
           out.write(outputByte, 0, 4096);
        }
    }
});

IOUtils.copy(in, response.getOutputStream());

请注意,强烈建议在不同的线程中进行写入,因此请确保您拥有某个执行程序的实例。

  

管道输出流可以连接到管道输入流   创建一个通信管道。管道输出流是发送   管道的尽头。通常,数据被写入PipedOutputStream   对象由一个线程和数据从连接中读取   PipedInputStream由其他一些线程组成。试图使用这两个对象   建议不要使用单个线程,因为它可能使线程死锁。   如果正在读取数据字节的线程,则称管道已损坏   来自连接的管道输入流不再存在。

所以这里发生的是你的线程A将数据写入管道输出流,线程B(它是一个servlet)从中读取并以块的形式将其发送回客户端。通过这种方式,您的客户端将在浏览器中看到自己的进度,如果工作时间很长,您将永远不会超时。

希望这有帮助。