Spring - 下载文件并重定向

时间:2013-08-16 13:56:22

标签: spring redirect spring-mvc download zip

我的页面上有一个下载链接可以正常工作,但它不会刷新/重定向我的页面。这是我的代码。

@RequestMapping(method = RequestMethod.POST, params = "exportToXML")
public String exportToXML(HttpServletResponse response, Model model, @ModelAttribute(FILTER_FORM) ScreenModel form,
        BindingResult result, OutputStream out,
        HttpSession session) throws IOException {
    ZipOutputStream zipout;
    ByteArrayOutputStream baos = new ByteArrayOutputStream();


        zipout = new ZipOutputStream(baos);
        ZipEntry ze = new ZipEntry("file.xml");
        zipout.putNextEntry(ze);
        zipout.write(string.getBytes());
        zipout.closeEntry();
        zipout.close();
        baos.close();


    response.setContentType("application/vnd.ms-excel");
    response.setHeader("Content-disposition", "attachment; filename=xx.zip");
    response.getOutputStream().write(baos.toByteArray());
    response.getOutputStream().close();
    response.getOutputStream().flush();
    return VIEW_NAME;
}

我删除了不相关的代码片段,使其缩短了一点。我也试过@ResponseBody,但它给出了与上面代码相​​同的结果。 任何建议都会有所帮助

6 个答案:

答案 0 :(得分:8)

您无法下载文件并进行刷新/重定向。 我会尝试解释原因。请求流程如下所示: enter image description here

其中黄色圆圈是您的控制器。当您返回视图名称时,前端控制器会查找相应的视图模板(只需jsp,tiles或其他,具体取决于已配置的视图解析器)获取响应并将生成的html(或非html)代码写入其中。

在您的情况下,您执行操作:

response.getOutputStream().write(baos.toByteArray());
response.getOutputStream().close();
response.getOutputStream().flush();

在该操作之后,spring无法打开响应并将刷新的页面写入其中(因为您之前已执行此操作)。 因此,您可以将方法签名更改为:

public void exportToXML(HttpServletResponse response, Model model, @ModelAttribute(FILTER_FORM) ScreenModel form,
        BindingResult result, OutputStream out,
        HttpSession session) throws IOException {

并删除最后一次"返回VIEW_NAME"。什么都不会改变。

答案 1 :(得分:3)

你可以:

response.setHeader("Refresh", "1; url = index");

在URL响应后1秒后刷新页面:"索引"。

答案 2 :(得分:1)

不会。浏览器在新窗口中打开ms-excel contentType,或者您会收到下载提示。启动下载的页面永远不会有机会处理重定向或页面转换。

如果需要下载+页面刷新,JavaScript函数可以启动下载并将用户引导到下一页,该页面可能会说“您的下载将很快开始”或类似的内容。

答案 3 :(得分:0)

您可以在下载后调用javascript函数向您提交控制器并显示其他页面。

答案 4 :(得分:0)

LottaLava的答案中,我有了解决类似问题的想法。

在JavaScript中,提交表单后,我等待了一个半秒,然后重新加载页面。等待时间是等待后端下载文件(此处为exportToXML)并返回响应,然后在JavaScript中刷新页面的时间。

form.submit();
sleep(1500).then(function() {
     document.location.reload();
});

在您的情况下,form.submit() exportToXML调用控制器操作。

sleep函数如下:

function sleep(milliseconds) {
    return new Promise(function (resolve) {
        setTimeout(resolve, milliseconds);
    });
}

sleep函数引用here

答案 5 :(得分:0)

我使用以下结构来解决我的问题。该函数提交表单并返回,换句话说,您下载文件并刷新上一个链接。使用此解决方案,您甚至可以使用某些模板渲染来显示和隐藏消息错误,在我的情况下,我使用的是 Thymeleaf

为了使代码更具可读性,我删除了 Thymeleaf 标签。

JS 文件:

function submitAndBack(formId) {
    let formDoc = document.getElementById(formId);
    formDoc.submit();
    sleep(1000).then(function() {
        window.history.back();
    });
}

function sleep(milliseconds) {
    return new Promise(function (resolve) {
        setTimeout(resolve, milliseconds);
    });
}

HTML 表单:

<form id="myForm" method="POST" action="/some/url">
      <label for="inputText">Some info</label>
      <input id="inputText" name="inputText" type="text">
      <button onclick="submitAndBack('myForm')">
          Submit
      </button>
</form>