4

I have a Client-Server application using SpringBoot and Angular2. I would like to load a image from the server by filename. This works fine.

I store the attribute image:string at the client and I place it in the template again. You might pay attention to return res.url;; I do not use the actual ressource, which might be wrong.

My objective is that image is cached. To my understanding the web-browser can automatically cache the images. Correct? But the caching does not work yet and maybe somebody could give me a hint what needs to be adjusted? Is a different header required?

Server (SpringBoot)

public class ImageRestController {
    @RequestMapping(value = "/getImage/{filename:.+}", method = RequestMethod.GET)
    public ResponseEntity<Resource> getImage(@PathVariable String filename) {

        try {
            String path = Paths.get(ROOT, filename).toString();
            Resource loader = resourceLoader.getResource("file:" + path);
            return new ResponseEntity<Resource>(loader, HttpStatus.OK);
        } catch (Exception e) {
            return new ResponseEntity<Resource>(HttpStatus.NOT_FOUND);
        }
    }
}   

Client (Angular2)

@Component({
  selector: 'my-image',
  template: `
    <img src="{{image}}"/>
  `
})

export class MyComponent {

  image:string;
  constructor(private service:MyService) {}

  showImage(filename:string) {
    this.service.getImage(filename)
      .subscribe((file) => {
          this.image = file;
        });
      }
}

export class MyService() {
  getImage(filename:String):Observable<any> {
    return this.http.get(imagesUrl + "getImage/" + filename)
      .map(this.extractUrl)
      .catch(this.handleError);
  }
  extractUrl(res:Response):string {
    return res.url;
  }
}
1
  • You could try sending HttpStatus.NOT_MODIFIED to clients you already served once. Commented Jul 7, 2016 at 11:02

1 Answer 1

3

You could do something like this on the server side (and perhaps add an ETag or Last-Modified header if you can get that information):

return ResponseEntity
            .ok()
            .cacheControl(CacheControl.maxAge(30, TimeUnit.DAYS))
            .body(loader);

See the HTTP caching part of the reference documentation in Spring.

If you're just serving resources and not applying any additional logic, then you'd better do the following:

@Configuration
public class WebConfig extends WebMvcConfigurerAdapter {

    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/getImage/**")
                .addResourceLocations("classpath:/path/to/root/")
                .setCacheControl(CacheControl.maxAge(1, TimeUnit.DAYS).cachePublic());
    }

}

See the other relevant part of the reference documentation. You can also apply transformations and leverage cache busting (see this section as well).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.