Pergunta

I am trying to write a controller that generates a CSV spreadsheet to save as a file.

I have written the following action and render methods

/**
 * Get the stats for the search.
 */
@ActionMapping(params={"controller=exportView","action=csv"})
public void viewInstance(ActionRequest request, ActionResponse response){
    response.setRenderParameter("controller", "exportView");
    response.setRenderParameter("action","csv");
}


@RenderMapping(params={"controller=exportView","action=csv"})
public String viewInstance(@RequestParam(value = "id", required = true) final String viewInstanceId, RenderRequest request, RenderResponse response, Model model) throws Exception {
    ApplicationContext ctx = ThreadApplicationContextHolder.getApplicationContext();

    .. do some stuff

    String filename = getFilename();

    response.setContentType("text/csv"); // go bang here

    response.addProperty(ExportViewInstanceAsCsvFileController.HEADER_CONTENT_DISPOSITION, "attachment;filename=" + filename + ExportViewInstanceAsCsvFileController.FILE_EXT);

    viewInstanceFileRenderer.renderSearchResultNodesToFile(getData(), response.getPortletOutputStream());

    return "portlet/exportView";
}

When it runs the server complains that the content type is not "text/html", so I amended the portlet.xml to have

<supports>
  <mime-type>text/html</mime-type>
  <portlet-mode>VIEW</portlet-mode>
</supports>
<supports>
  <mime-type>text/csv</mime-type>
  <portlet-mode>VIEW</portlet-mode>
</supports>

but websphere seems to be ignoring this.

When I debug and run request.getResponseContentTypes() it only has text/html in the collection. The application structure has a portlet to handle logons and then three web applications to handle various aspects of the application. I have modified the portlet in the web application that handles the spreadsheet generation, but not in the logon portlet.

My next step is to change that(the logon portlet.xml) but I am not confident it will work.

Are there any other places I can look?

Foi útil?

Solução

You'll want to implement ResourceServingPortlet and have your portlet class implement serveResource. In it you can set the content type and other headers just as you attempted in action and render responses. Only this time, your portlet will own the response as opposed to merely contributing to it. You'll need to render a link for example to your resource URL which you can obtain from your RenderResponse in doView().

End-to-end, you'll do something like this:

  1. In doView(), obtain a ResourceURL to your serveResource() method from the RenderResponse.
  2. render an HTML fragment with, for example, a "download CSV" hyperlink whose href is the ResourceURL you obtained. When the browser requests it your serveResource() method will be invoked.
  3. Set your headers and write your binary / stream to the response.

Hope this helps,

  • Scott
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top