Pergunta

Uma das ações de meu controlador JPF acumula um arquivo PDF e eu gostaria de voltar este arquivo para o usuário para que ele possa baixá-lo.

É possível fazer isso ou estou forçado a escrever a algum arquivo e ter a minha ação para a frente um link para este arquivo? Nota que eu gostaria de evitar que, tanto quanto possível, por razões de segurança e porque eu não tenho nenhuma maneira de saber quando o usuário tenha baixado o arquivo para que eu possa excluí-lo.

Eu tentei acesso a HttpServletResponse mas nada acontece:

getResponse().setContentLength(file.getSize());
getResponse().setContentType(file.getMimeType());
getResponse().setHeader("Content-Disposition", "attachment;filename=\"" + file.getTitle() + "\"");
getResponse().getOutputStream().write(file.getContent());
getResponse().flushBuffer();
Foi útil?

Solução

Temos algo semelhante, exceto retornando imagens em vez de um PDF; deve ser uma solução semelhante, porém, eu estou supondo.

Em um JSP, temos uma tag IMG, onde o src está definido para:

<c:url value="/path/getImage.do?imageId=${imageID}" />

(eu não estou mostrando tudo, porque eu estou tentando simplificar.) No seu caso, talvez fosse um link, onde o href é feito de uma forma similar.

Isso getImage.do mapeia para nosso controlador JPF, obviamente. Aqui está o código do método getImage() JPF, que é a parte que você está tentando trabalhar em:

@Jpf.Action(forwards = {
    @Jpf.Forward(name = FWD_SUCCESS, navigateTo = Jpf.NavigateTo.currentPage),
    @Jpf.Forward(name = FWD_FAILURE, navigateTo = Jpf.NavigateTo.currentPage) })
public Forward getImage(final FormType pForm) throws Exception {
  final HttpServletRequest lRequest = getRequest();
  final HttpServletResponse lResponse = getResponse();
  final HttpSession lHttpSession = getSession();
  final String imageIdParam = lRequest.getParameter("imageId");

  final long header = lRequest.getDateHeader("If-Modified-Since");
  final long current = System.currentTimeMillis();

  if (header > 0 && current - header < MAX_AGE_IN_SECS * 1000) {
    lResponse.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
    return null;
  }

  try {
    if (imageIdParam == null) {
      throw new IllegalArgumentException("imageId is null.");
    }

    // Call to EJB, which is retrieving the image from
    // a separate back-end system
    final ImageType image = getImage(lHttpSession, Long
        .parseLong(imageIdParam));

    if (image == null) {
      lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
      return null;
    }

    lResponse.setContentType(image.getType());
    lResponse.addDateHeader("Last-Modified", current);
    // public: Allows authenticated responses to be cached.
    lResponse.setHeader("Cache-Control", "max-age=" + MAX_AGE_IN_SECS
        + ", public");
    lResponse.setHeader("Expires", null);
    lResponse.setHeader("Pragma", null);
    lResponse.getOutputStream().write(image.getContent());

  } catch (final IllegalArgumentException e) {
    LogHelper.error(this.getClass(), "Illegal argument.", e);
    lResponse.sendError(404, IMAGE_DOES_NOT_EXIST);
  } catch (final Exception e) {
    LogHelper.error(this.getClass(), "General exception.", e);
    lResponse.sendError(500);
  }
  return null;
}

Eu realmente removido muito pouco a partir deste método, porque há muito pouco lá dentro que eu preciso esconder de olhos curiosos - o código é bastante genérico, preocupada com imagens, não com lógica de negócios. (Eu mudei alguns dos nomes de tipos de dados, mas não é grande coisa.)

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