Tengo un servidor web que ejecuta con Jersey RESTO de recursos y me pregunto cómo obtener una image/png de referencia para los navegadores de la etiqueta img; después de la presentación de un Formulario o la obtención de una respuesta Ajax. El procesamiento de la imagen el código para añadir gráficos está trabajando, sólo tiene que devolver de alguna manera.

Código:

@POST
@Path("{fullsize}")
@Consumes(MediaType.MULTIPART_FORM_DATA)
@Produces("image/png")
//Would need to replace void
public void getFullImage(@FormDataParam("photo") InputStream imageIS,
                         @FormDataParam("submit") String extra) {

      BufferedImage image = ImageIO.read(imageIS);

      //.... image processing
      //.... image processing

      return ImageIO.  ..  ?

}

Saludos

  • ¿Qué estás tratando de lograr? No se puede lograr esto mediante el envío de un URI con la ubicación de la imagen?
  • Quiero que el usuario de la vista previa de las imágenes seleccionadas en la foto antes de poner un poco de orden. Ahora veo que esto no se puede hacer con AJAX post, tendrá que solicitar a las páginas web como usted dice señalando a la imagen procesada.
InformationsquelleAutor gorn | 2012-02-09

4 Comentarios

  1. 91

    No estoy convencido de que es una buena idea para volver los datos de la imagen en un servicio REST. Que restringe la aplicación del servidor de memoria y de e /s de ancho de banda. Mucho mejor delegar esa tarea a una adecuada servidor web que está optimizado para este tipo de transferencia. Usted puede lograr esto mediante el envío de una redirección a la imagen de los recursos (como una respuesta HTTP 302 con el URI de la imagen). Esto supone, por supuesto, que sus imágenes están organizadas como contenido de la web.

    Habiendo dicho esto, si usted decide que usted realmente necesita para transferir los datos de la imagen a partir de un servicio web, puede hacerlo con el siguiente (pseudo) código:

    @Path("/whatever")
    @Produces("image/png")
    public Response getFullImage(...) {
    
        BufferedImage image = ...;
    
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        ImageIO.write(image, "png", baos);
        byte[] imageData = baos.toByteArray();
    
        //uncomment line below to send non-streamed
        //return Response.ok(imageData).build();
    
        //uncomment line below to send streamed
        //return Response.ok(new ByteArrayInputStream(imageData)).build();
    }

    Agregar en el manejo de excepciones, etc, etc.

    • Gracias! Que es una manera de hacerlo.
    • Terminó con PHP de la aplicación de servidor que utiliza cURL para obtener imágenes de este RESTful en Java web service y se refirió a ellos en el código HTML de la etiqueta de imagen.
    • usted debe escribir la solución en su respuesta como una edición
    • Gracias de antemano
    • Sería agradable si usted podría completar su respuesta por medio de la prestación de código que hace como usted sugiere en su párrafo inicial, podría ser útil si alguien (me dicen jeje) fue convencido por su argumento.
    • Para bajar su bandwitch puede agregar CacheControl a la Respuesta CacheControll cc = new CacheControl(); cc.setMaxAge(number); Response(..).cacheControl(cc).build();.
    • Tal vez esta respuesta por BalusC puede ayudar a los demás, que se relaciona con el párrafo de apertura: stackoverflow.com/questions/4543936/…

  2. 12

    He construido un método general para que, con las siguientes características:

    • volver «no modificado» si el archivo no ha sido modificado localmente, un Estado.NOT_MODIFIED se envía a la persona que llama. Utiliza Apache Commons Lang
    • mediante una secuencia de archivo de objeto en lugar de leer el archivo en sí

    Aquí el código:

    import org.apache.commons.lang3.time.DateUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    private static final Logger logger = LoggerFactory.getLogger(Utils.class);
    @GET
    @Path("16x16")
    @Produces("image/png")
    public Response get16x16PNG(@HeaderParam("If-Modified-Since") String modified) {
    File repositoryFile = new File("c:/temp/myfile.png");
    return returnFile(repositoryFile, modified);
    }
    /**
    * 
    * Sends the file if modified and "not modified" if not modified
    * future work may put each file with a unique id in a separate folder in tomcat
    *   * use that static URL for each file
    *   * if file is modified, URL of file changes
    *   * -> client always fetches correct file 
    * 
    *     method header for calling method public Response getXY(@HeaderParam("If-Modified-Since") String modified) {
    * 
    * @param file to send
    * @param modified - HeaderField "If-Modified-Since" - may be "null"
    * @return Response to be sent to the client
    */
    public static Response returnFile(File file, String modified) {
    if (!file.exists()) {
    return Response.status(Status.NOT_FOUND).build();
    }
    //do we really need to send the file or can send "not modified"?
    if (modified != null) {
    Date modifiedDate = null;
    //we have to switch the locale to ENGLISH as parseDate parses in the default locale
    Locale old = Locale.getDefault();
    Locale.setDefault(Locale.ENGLISH);
    try {
    modifiedDate = DateUtils.parseDate(modified, org.apache.http.impl.cookie.DateUtils.DEFAULT_PATTERNS);
    } catch (ParseException e) {
    logger.error(e.getMessage(), e);
    }
    Locale.setDefault(old);
    if (modifiedDate != null) {
    //modifiedDate does not carry milliseconds, but fileDate does
    //therefore we have to do a range-based comparison
    //1000 milliseconds = 1 second
    if (file.lastModified()-modifiedDate.getTime() < DateUtils.MILLIS_PER_SECOND) {
    return Response.status(Status.NOT_MODIFIED).build();
    }
    }
    }        
    //we really need to send the file
    try {
    Date fileDate = new Date(file.lastModified());
    return Response.ok(new FileInputStream(file)).lastModified(fileDate).build();
    } catch (FileNotFoundException e) {
    return Response.status(Status.NOT_FOUND).build();
    }
    }
    /*** copied from org.apache.http.impl.cookie.DateUtils, Apache 2.0 License ***/
    /**
    * Date format pattern used to parse HTTP date headers in RFC 1123 format.
    */
    public static final String PATTERN_RFC1123 = "EEE, dd MMM yyyy HH:mm:ss zzz";
    /**
    * Date format pattern used to parse HTTP date headers in RFC 1036 format.
    */
    public static final String PATTERN_RFC1036 = "EEEE, dd-MMM-yy HH:mm:ss zzz";
    /**
    * Date format pattern used to parse HTTP date headers in ANSI C
    * <code>asctime()</code> format.
    */
    public static final String PATTERN_ASCTIME = "EEE MMM d HH:mm:ss yyyy";
    public static final String[] DEFAULT_PATTERNS = new String[] {
    PATTERN_RFC1036,
    PATTERN_RFC1123,
    PATTERN_ASCTIME
    };

    Nota de que la configuración Regional de conmutación no parece ser seguro para subprocesos. Creo que es mejor cambiar la configuración regional a nivel mundial. No estoy seguro acerca de los efectos secundarios, aunque…

    • Puede eliminar una gran cantidad de su última modificación de la lógica mediante el uso de Jersey de la Solicitud.evaluatePreconditions(…), como se ocupará de analizar y comprobar las fechas, y etags si los apoyan.
  3. 7

    respecto de la respuesta de @Percepción, su verdadero ser muy de consumo de memoria cuando se trabaja con matrices de bytes, pero también puede simplemente escribir de nuevo en el outputstream

    @Path("/picture")
    public class ProfilePicture {
    @GET
    @Path("/thumbnail")
    @Produces("image/png")
    public StreamingOutput getThumbNail() {
    return new StreamingOutput() {
    @Override
    public void write(OutputStream os) throws IOException, WebApplicationException {
    //... read your stream and write into os
    }
    };
    }
    }
  4. 6

    Si usted tiene un número de recursos de imagen de los métodos, es bien vale la pena crear un MessageBodyWriter a la salida de la BufferedImage:

    @Produces({ "image/png", "image/jpg" })
    @Provider
    public class BufferedImageBodyWriter implements MessageBodyWriter<BufferedImage>  {
    @Override
    public boolean isWriteable(Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
    return type == BufferedImage.class;
    }
    @Override
    public long getSize(BufferedImage t, Class<?> type, Type type1, Annotation[] antns, MediaType mt) {
    return -1; //not used in JAX-RS 2
    }
    @Override
    public void writeTo(BufferedImage image, Class<?> type, Type type1, Annotation[] antns, MediaType mt, MultivaluedMap<String, Object> mm, OutputStream out) throws IOException, WebApplicationException {
    ImageIO.write(image, mt.getSubtype(), out);
    } 
    }

    Este MessageBodyWriter será utilizado automáticamente si la detección automática está habilitada para Jersey, de lo contrario debe ser devuelto por una Aplicación personalizada sub-clase. Ver JAX-RS Entidad Proveedores para obtener más información.

    Vez configurado, simplemente devuelva un BufferedImage de un recurso de método y que será la salida como archivo de imagen de datos:

    @Path("/whatever")
    @Produces({"image/png", "image/jpg"})
    public Response getFullImage(...) {
    BufferedImage image = ...;
    return Response.ok(image).build();
    }

    Un par de ventajas de este enfoque:

    • Escribe la respuesta OutputSteam en lugar de un intermediario BufferedOutputStream
    • Es compatible tanto con el png y jpg de salida (dependiendo de los tipos de medios permitidos por el recurso del método)

Dejar respuesta

Please enter your comment!
Please enter your name here