【问题标题】:How to hide an animated gif after the file has been downloaded ?文件下载后如何隐藏动画 gif?
【发布时间】:2016-05-04 02:37:09
【问题描述】:

在执行一些服务器端 Java 代码并且客户端从网络服务器获取 HTTP 响应而不使用 Ajax 后,有没有办法让动画 gif 图像消失?

我正在使用以下 Struts2 提交按钮:

<s:submit value="show Data" onclick="myJsFunction()" />

gif动画图片的显示方法:

function myJsFunction(){  
    $("#containerWithGifImage").fadeIn("fast");  
} 

动画gif图像消失的方法(但我不知道,没有Ajax我怎么能调用它):

 function myJsFunction2(){  
     $("#containerWithGifImage").fadeOut("fast");  
 }  

现在 gif 出现了,但是在 webserver 上的 java 代码执行后它并没有消失。

【问题讨论】:

  • 你怎么叫myJsFunction2
  • 您提交的表单并非如此。对于删除/隐藏内容页面显示的元素,您需要使用 ajax 否则提交表单将重定向/刷新当前页面(在您的情况下再次显示 gif 图像,我想)...您最终可以通过表单操作传递查询参数,但是不知道你在这里真正期待什么
  • 当服务器工作时,该动作被执行,并在它返回一个可能会将您重定向到另一个页面的结果之后。
  • @RomanC: 动作执行后必须留在同一个网页上!
  • @Marwief 然后你需要在新窗口中执行操作。

标签: javascript java jquery ajax struts2


【解决方案1】:

您的两个问题(this 和 the other one)都是 XY problem 的示例。

在寻找特定技术、技巧或技巧之前,请先明确定义您的目标:

目标

  1. 下载文件而不移动到其他页面;
  2. 同时,显示一个指示器(进度条、动画 gif、叠加层等...);
  3. 下载文件后,隐藏指示器。

解决方案

将您的触发器绑定到一个javascript函数as described here

<a href="javascript:myJsFunction();"> download </a>

在您的 Javascript 函数中:显示指示器,启动计时器以检查下载是否结束(然后隐藏指示器),然后下载文件:

 function myJsFunction(){

    $("#containerWithGifImage").fadeIn("fast"); // Show the indicator

    setInterval(function(){
        $.ajax({
                url : "/isDownloadFinished.action", type : "GET",
            success : function(data,textStatus,jqXHR) {
                $("#containerWithGifImage").fadeOut("fast"); // Hide the indicator
            },error : function(jqXHR, textStatus, errorThrown) {
                console.log("Download is still in progress, do nothing..."); 
            }
        }); 
    }, 1000); // Check every second if download has finished

    window.location='/download.action'; // Start the download
}

Download.action 必须在会话中添加一个属性,指示下载已开始,并在下载结束时更新。
由于使用stream 结果,您将响应的控制权委托给浏览器(因此在完成后您无法运行代码),您可以直接写入响应,然后返回NONE、@987654324 @:

public class Download extends ActionSupport implements SessionAware, ServletResponseAware {

    @Setter private Map session;
    @Setter private HttpServletResponse response;

    public String execute(){
        ServletOutputStream os = null;
        try {
            session.put("DOWNLOAD_STATUS","active");
            response.setContentType("myContentType"); 
            response.addHeader("Content-Disposition", "attachment; filename=\"foo.bar\"");
            os = response.getOutputStream();
            IOUtils.copy(getMyFileInputStreamSomeHow(), os);
        } finally {
            IOUtils.closeQuietly(os);
            session.put("DOWNLOAD_STATUS","finished");
        }
        return NONE;
    }
}

您还可以通过指定 Content-Length 响应标头 (response.setHeader("Content-Length", 1337);) as described here 让浏览器为您绘制进度条,您还可以在其中看到类似的机制来防止并发下载。

IsDownloadFinished.action中,需要勾选session属性。如果它不存在或与已完成不同,则表示下载尚未开始或仍在进行中,因此什么也不做。否则,返回一个成功的 httpheader,这将使您的 jQuery $.ajax 函数运行success: 回调。您可以使用httpHeaderjsonas described here

@Results({
    @Result(name = ActionSupport.SUCCESS, type="httpheader", params = {"status", "200"}),
    @Result(name = ActionSupport.ERROR,   type="httpheader", params = {"error",  "500"})
})
public class IsDownloadFinished extends ActionSupport implements SessionAware {

    @Setter private Map session;

    public String execute(){            
        if ("finished".equals(session.get("DOWNLOAD_STATUS")) {
            session.remove("DW_STATUS");
            return SUCCESS;
        }
        return ERROR;
    }
}

这个问题有不同的解决方案,我向您展示了最简单的一个。
更优雅和复杂的解决方案将涉及长期持有的请求和Comet techniques(阅读:WebSocket),但我想您可以从这个启动示例中的轮询计时器开始,根据您的需要对其进行自定义,最终在对论点更满意时对其进行改进。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2020-06-02
    • 2013-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-07-13
    • 2020-10-12
    相关资源
    最近更新 更多