为什么我的 JavaScript 中的 setTimeout 函数无法正确执行多轮下载?

问题描述 投票:0回答:1

我尝试使用

setTimeout
top.location.href
在 JSP 页面中顺序下载多个文件,但下载过程未按预期运行。它似乎只处理第一个文件并跳过其他文件,而不是在单独的轮次中执行每个下载(有 2 秒的延迟)。

这是我的代码的简化版本:

<%@page language="java"%>
<%@ page import="java.util.*, java.text.*, java.sql.*"%>
<%@ page import="java.io.*"%>
<%@ page import="sapphire.accessor.QueryProcessor, sapphire.util.DataSet, sapphire.util.StringUtil, sapphire.util.ActionBlock, sapphire.accessor.ActionProcessor, sapphire.util.DBAccess, sapphire.accessor.ActionException"%>
<%@ taglib uri="/WEB-INF/tlds/sapphire.tld" prefix="sapphire" %>
<%@ taglib uri="/WEB-INF/tlds/c.tld" prefix="c" %>
<sapphire:controlledpage allowanonymous="true"/>
<sapphire:page layout="${layout.objectname}">
<sapphire:pagecontent name="content">

<%!
    public void writeLog(String logstr) {
        String pathFile = "D:\\GenControlChartLog.txt";
        try {
            PrintWriter out = new PrintWriter(new BufferedWriter(new FileWriter(pathFile, true)));
            out.println(new java.util.Date() + " - " + logstr);
            out.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
%>

<%
    writeLog("Start processing control charts");
    String data = requestinfo.getProperty("data");
    String sdate = requestinfo.getProperty("sdate");
    String edate = requestinfo.getProperty("edate");
    String scno = requestinfo.getProperty("scno");
    String[] _data = data.split("%3B");
    String filenameall = "";
    for(int i = 0;i<_data.length;i++) {
        String[] __data = _data[i].split(";");
        String filename = "ControlChart-"+__data[0]+"-"+i+"-" + new SimpleDateFormat("dd-MM-yyyy-HH-mm-ss").format(new java.util.Date()) +".xlsx";
        String success = "";
        writeLog("filename = "+ filename);
        HashMap hm = new HashMap();
        hm.put("filename", filename);
        hm.put("keyid1", _data[i]);
        hm.put("sdate", sdate);
        hm.put("edate", edate);
        hm.put("scno", scno);
        ActionProcessor ap = new ActionProcessor(application.getInitParameter("nameserverlist"), pageinfo.getConnectionId());
        try {
            ap.processAction("ControlChartXLXS", "1", hm);
            success = "SUCCESS";    
            writeLog("ControlChartXLXS SUCCESS ");
        } catch (ActionException ae) {
            success = "FAILURE";
            writeLog("error1 :"+ae.getMessage());
        } catch (Exception e) {
            success = "FAILURE";
            writeLog("error2 :"+e.getMessage());
        }
        if(i>0) {
            filenameall +="%3B";
        }
        filenameall +=filename;
    }
%>

<script>
    function downloadFile_V2(file, i) {
        setTimeout(function() {
            top.sapphire.alert( 'into setTimeout Download round ' + i, true );
            console.log('into setTimeout Download round ' + i);
            top.location.href = "WEB-CUSTOM/Download/DownloadFile_00.jsp?filepath=WEB-CUSTOM/ControlChart/Output/" + file;
        }, i * 2000); 
    }

    var _filename = "<%=filenameall%>";
    console.log('filearrOG = ' + _filename);
    if (_filename != "") {
        var filearr = _filename.split("%3B");
        console.log('filearr after split = ' + filearr);
        top.sapphire.alert('filearr length = ' + filearr.length, true);
        for (let i = 0; i < filearr.length; i++) {
            top.sapphire.alert('filearr = ' + filearr[i], true);
            console.log('filearr = ' + filearr[i]);
            downloadFile_V2(filearr[i], i);
        }
    } else {
        top.sapphire.alert('Not Found Document Template!', true);
    }
</script>

</sapphire:pagecontent>
</sapphire:page>

问题:

downloadFile_V2 函数应该按顺序触发下载,每轮之间有 2 秒的延迟。但是,仅发生第一次下载,其他下载将被跳过或不触发。

我希望日志显示 进入 setTimeout 下载第 0 轮 进入 setTimeout 下载第 1 轮 进入 setTimeout 下载第 2 轮

但是,它只记录第一轮(进入 setTimeout 下载第 0 轮)。 我尝试过的:

每次下载使用 setTimeout,延迟 i * 2000。 检查了 filearr 数组的长度,看起来是正确的。 检查了是否有任何 JavaScript 错误,但没有显示任何错误。 关于为什么会发生这种情况或者如何解决这个问题有什么建议吗?

javascript jsp
1个回答
0
投票

出现您面临的问题是因为当您使用

top.location.href
时,它会触发页面导航,从而中断后续 JavaScript 代码的执行。这会导致页面重新加载时仅下载第一个文件,而其他下载请求没有机会执行。

您可以通过动态创建隐藏锚点 (

top.location.href
) 元素来触发下载,而不是使用
<a>
。这允许您按顺序下载文件,而不会导致页面导航。

以下是更新

downloadFile_V2
功能的方法:

function downloadFile_V2(file, i) {
    setTimeout(function() {
        console.log('into setTimeout Download round ' + i);

        // Create a hidden <a> element to trigger the download
        var link = document.createElement('a');
        link.href = "WEB-CUSTOM/Download/DownloadFile_00.jsp?filepath=WEB-CUSTOM/ControlChart/Output/" + file;
        link.download = file; // Set the download attribute to the filename

        // Append the link to the body, click it to trigger the download, and then remove it
        document.body.appendChild(link);
        link.click();
        document.body.removeChild(link);
    }, i * 2000); // Set a 2-second delay between each download
}

var _filename = "<%=filenameall%>";
if (_filename != "") {
    var filearr = _filename.split("%3B");
    for (let i = 0; i < filearr.length; i++) {
        downloadFile_V2(filearr[i], i);
    }
} else {
    console.log('No files found.');
}
© www.soinside.com 2019 - 2024. All rights reserved.