Pregunta

Una de las acciones de mi controlador de JPF acumula un archivo PDF y me gustaría devolver este archivo al usuario para que pueda descargarlo.

¿Es posible hacer eso o estoy obligado a escribir el archivo en algún lugar y tienen mi acción hacia adelante un enlace a este archivo? Note que le gustaría evitar que tanto como sea posible por razones de seguridad y porque no tengo manera de saber cuándo el usuario ha descargado el archivo para que pueda eliminarlo.

He intentado acceder a la HttpServletResponse pero no pasa nada:

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

Solución

Tenemos algo similar, excepto regresar imágenes en lugar de un archivo PDF; debe ser una solución similar, aunque, supongo.

En un JSP, tenemos una etiqueta IMG, donde el src se establece en:

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

(no estoy mostrando todo, porque estoy tratando de simplificar.) En su caso, tal vez sería un enlace, donde el href se realiza de una manera similar.

que los mapas getImage.do a nuestro controlador JPF, obviamente. Aquí está el código del método getImage() JPF, que es la parte que está tratando de trabajar en:

@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;
}

De hecho, he quitado muy poco de este método, ya que hay muy poco allí que necesito para ocultar de miradas indiscretas - el código es bastante genérico, que se trate con imágenes, no con la lógica de negocio. (He cambiado algunos de los nombres de tipos de datos, pero no es gran cosa.)

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top