How do I use Spring Boot to serve static content located in Dropbox folder?

I have a Spring Boot web application, and I would like to serve static content located in a shared Dropbox directory on my Linode VPS (~/Dropbox/images). I've read that Spring Boot will automatically serve static content from

"classpath:/META-INF/resources/",
"classpath:/resources/",
"classpath:/static/",
"classpath:/public/",

but of course my Dropbox directory is not on the classpath.

Although I could configure Apache to serve the images in my Dropbox folder, I would like to take advantage of Spring Security to restrict access of the static content to authenticated users.


Solution 1:

You can add your own static resource handler (it overwrites the default), e.g.

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {
    @Override
    public void addResourceHandlers(ResourceHandlerRegistry registry) {
        registry.addResourceHandler("/**").addResourceLocations("file:/path/to/my/dropbox/");
    }
}

There is some documentation about this in Spring Boot, but it's really just a vanilla Spring MVC feature.

Also since spring boot 1.2 (I think) you can simply set spring.resources.staticLocations.

Solution 2:

Springboot (via Spring) now makes adding to existing resource handlers easy. See Dave Syers answer. To add to the existing static resource handlers, simply be sure to use a resource handler path that doesn't override existing paths.

The two "also" notes below are still valid.

. . .

[Edit: The approach below is no longer valid]

If you want to extend the default static resource handlers, then something like this seems to work:

@Configuration
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class CustomWebMvcAutoConfig extends
                    WebMvcAutoConfiguration.WebMvcAutoConfigurationAdapter {

  @Override
  public void addResourceHandlers(ResourceHandlerRegistry registry) {
    String myExternalFilePath = "file:///C:/Temp/whatever/m/";

    registry.addResourceHandler("/m/**").addResourceLocations(myExternalFilePath);

    super.addResourceHandlers(registry);
  }

}

The call to super.addResourceHandlers sets up the default handlers.

Also:

  • Note the trailing slash on the external file path. (Depends on your expectation for URL mappings).
  • Consider reviewing the source code of WebMvcAutoConfigurationAdapter.

Solution 3:

Based on @Dave Syers answer I add the following class to my Spring Boot project:

@Configuration
public class StaticResourceConfiguration extends WebMvcConfigurerAdapter {

 private static final Logger LOG = LoggerFactory.getLogger(StaticResourceConfiguration.class);

 @Value("${static.path}")
 private String staticPath;

 @Override
 public void addResourceHandlers(ResourceHandlerRegistry registry) {

    if(staticPath != null) {
        LOG.info("Serving static content from " + staticPath);
        registry.addResourceHandler("/**").addResourceLocations("file:" + staticPath);
    }
 }

 // see https://stackoverflow.com/questions/27381781/java-spring-boot-how-to-map-my-my-app-root-to-index-html
 @Override
 public void addViewControllers(ViewControllerRegistry registry) {
    registry.addViewController("/").setViewName("redirect:/index.html");
 }
}

This allows me to start my spring boot app with the parameter --static.path like

java -jar spring-app-1.0-SNAPSHOT.jar --static.path=/path/to/my/static-files/

This can be very handy for development and testing.

Solution 4:

There's a property spring.resources.staticLocations that can be set in the application.properties. Note that this will override the default locations. See org.springframework.boot.autoconfigure.web.ResourceProperties.

Solution 5:

  • OS: Win 10
  • Spring Boot: 2.1.2

I wanted to serve static content from c:/images

Adding this property worked for me:

spring.resources.static-locations=classpath:/META-INF/resources/,classpath:/resources/,classpath:/static/,classpath:/public/,file:///C:/images/

I found the original value of the property in the Spring Boot Doc Appendix A

This will make c:/images/image.jpg to be accessible as http://localhost:8080/image.jpg