How to return a PNG image from Jersey REST service method to the browser

前端 未结 4 1900
粉色の甜心
粉色の甜心 2020-11-30 19:46

I have a web server running with Jersey REST resources up and I wonder how to get an image/png reference for the browsers img tag; after submitting a Form or getting an Ajax

4条回答
  •  误落风尘
    2020-11-30 20:09

    I built a general method for that with following features:

    • returning "not modified" if the file hasn't been modified locally, a Status.NOT_MODIFIED is sent to the caller. Uses Apache Commons Lang
    • using a file stream object instead of reading the file itself

    Here the code:

    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
     * asctime() 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
    };
    

    Note that the Locale switching does not seem to be thread-safe. I think, it's better to switch the locale globally. I am not sure about the side-effects though...

提交回复
热议问题