Grails创建可下载的文件

时间:2013-01-21 08:51:18

标签: jquery ajax grails download

我在视图中调用以下jQuery函数:

$.ajax({
                    url: '${request.contextPath + '/Ticket/passAll'}',
                    type: 'POST',
                    data: Data,

                    success: function(result) {


                        $('#export_form').submit();
                    }


                });

在控制器中,我正在对传递的数据进行一些过滤和格式化,并且在方法的最后我将这些数据放入会话中:

session["export"] = filteredData
render "success"

如果成功,$ .ajax()会提交export_form表单,该表单只调用控制器中的另一个函数,该函数将数据设置为附件下载。

    def filter = session["export"].toString()

    def tickets = Ticket.findAll("from Ticket as t ${filter}", [])
    session["export"] = null

    OutputStream outputStream = response.getOutputStream();
    outputStream.write(0xEF);
    outputStream.write(0xBB);
    outputStream.write(0xBF);

    response.setHeader("Content-disposition", "attachment; filename=tickets.csv")
    response.setContentType("application/vnd.ms-excel:UTF-8")


    def outs = response.outputStream
    def cols = [:]

    outs << "TicketNo;Ticket Details\n"

    tickets.each() {        
        outs << it.ticketNo + ";" + it.ticketDetails

        outs << "\n"

    }

    outs.flush()
    outs.close()

这正在开发中,但是当我在Tomcat上部署它时,我遇到了以下错误:

org.codehaus.groovy.grails.web.pages.exceptions.GroovyPagesException: Error processing GroovyPageView: getOutputStream() has already been called for this response
org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.createGroovyPageException(GroovyPageView.java:205)
org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.handleException(GroovyPageView.java:181)
org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.renderWithTemplateEngine(GroovyPageView.java:152)
org.codehaus.groovy.grails.web.servlet.view.GroovyPageView.renderMergedOutputModel(GroovyPageView.java:83)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:262)
org.codehaus.groovy.grails.web.sitemesh.SpringMVCViewDecorator.render(SpringMVCViewDecorator.java:67)
org.codehaus.groovy.grails.web.sitemesh.SpringMVCViewDecorator.render(SpringMVCViewDecorator.java:52)
org.codehaus.groovy.grails.web.sitemesh.GrailsPageFilter.doFilter(GrailsPageFilter.java:160)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:369)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.authentication.rememberme.RememberMeAuthenticationFilter.doFilter(RememberMeAuthenticationFilter.java:119)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:187)
org.codehaus.groovy.grails.plugins.springsecurity.RequestHolderAuthenticationFilter.doFilter(RequestHolderAuthenticationFilter.java:40)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.codehaus.groovy.grails.plugins.springsecurity.MutableLogoutFilter.doFilter(MutableLogoutFilter.java:79)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:381)
org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:168)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
org.codehaus.groovy.grails.web.servlet.mvc.GrailsWebRequestFilter.doFilterInternal(GrailsWebRequestFilter.java:69)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.codehaus.groovy.grails.web.filters.HiddenHttpMethodFilter.doFilterInternal(HiddenHttpMethodFilter.java:65)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:346)
org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:259)
root cause

java.lang.IllegalStateException: getOutputStream() has already been called for this response
    gsp_helpdesk_layoutsmain_gsp.run(gsp_helpdesk_layoutsmain_gsp.groovy:47)
编辑:我正在页面上使用jQuery DataTables和Twitter Bootstrap插件。调用导出操作的表和按钮都位于<g:uploadForm>

我用这行代码在datables代码中生成按钮:

$("div.additional_filters").html('<g:actionSubmit value="${message(code: "datatables.passAll")}" action="export_test" class="btn btn-primary"/> );

发生了什么以及如何解决这个问题?谢谢。

我知道这不是正确的方法,但目前必须像这样做,所以请耐心等待。

1 个答案:

答案 0 :(得分:0)

您应该在写入输出之前编写所有HTTP标头(稍后在实际内容之后设置内容类型):

response.setHeader("Content-disposition", "attachment; filename=tickets.csv")
response.setContentType("application/vnd.ms-excel; charset=UTF-8")

OutputStream outputStream =  response.getOutputStream();
outputStream.write(0xEF);
outputStream.write(0xBB);
outputStream.write(0xBF);

据我所知,如果你的内容类型是'text / html'(它是默认值),那么Grails会尝试为你的动作呈现一个gsp视图(并在那里失败)。

你应该return null