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

12

78

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.

Leach answered 14/1, 2014 at 20:33 Comment(0)
M
82

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.

Mastoiditis answered 14/1, 2014 at 21:39 Comment(10)
I'm not finding the super class WebMvcAdapter in your example above. Which Spring JAR contains that class?Leach
I extended WebMvcConfigurerAdapter instead.Leach
As @Discontent mentioned, don't forget the trailing slash on the Resource Location path.Dorinedorion
To leave default resources mapping and add dropbbox folder as addition resources is recomended rename resourceHandler path, for sample: registry.addResourceHandler("/files/**").addResourceLocations("file:/path/to/my/dropbox/");Plexiglas
link for page not found. Since this is the accepted answer with a significant amount of votes may I suggest an update on this?Jackie
It even works for relative directory with "file:./dir/"Archicarp
Make sure that the addResourceLocations paths ends with /, otherwise, it causes 404Princeling
FYI this has at least one caveat: it will not map / to /index.html WelcomePageHandlerMapping uses resource.static-locations so it's harder to simulate via code.Tennies
Is this still the best way to do this in 2020? Given "WebMvcConfigurerAdapter" is deprecated in newer versions of spring.Whitford
WebMvcConfigurerAdapter was only deprecated in favour of its interface (read the javadocs). So it's the same.Mastoiditis
D
35

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.
Discontent answered 14/11, 2014 at 21:46 Comment(3)
Awesome, thanks for this! I'd also mention that it's important to include the trailing /** on the resource handler mapping as well, I forgot to add that and I kept getting 404 errorsNobles
This solution goes in the right direction, however it's not possible to inherit from WebMvcAutoConfigurationAdapter because the constructor arguments are not all public.Aluminize
@GeoffroyWarin This answer was originally written for older versions. I edited it just now to indicate that. See Dave Syer's answer. To add to existing resource handlers simply be sure not to override existing resource paths.Discontent
C
21

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://mcmap.net/q/141989/-java-spring-boot-how-to-map-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.

Carpus answered 15/5, 2015 at 10:14 Comment(1)
Is there a way use 'index.html' instead of '/' directly without redirecting?Takishatakken
A
10

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.

Apotheosize answered 22/11, 2015 at 5:59 Comment(1)
spring.resources.staticLocations is deprecated, but you can use spring.web.resources.staticLocations instead.Ackley
T
10

Based on @Dave Syer, @kaliatech and @asmaier answers the springboot v2+ way would be:

@Configuration
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class)
public class StaticResourceConfiguration implements WebMvcConfigurer  {

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

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

  }

}
Tutelage answered 16/1, 2019 at 7:3 Comment(1)
@AutoConfigureAfter(DispatcherServletAutoConfiguration.class) adding this saved my day. ThanksArmidaarmiger
H
10
  • 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

Hydrogenize answered 2/4, 2019 at 20:22 Comment(2)
spring.resources.static-locations is deprecated, but you can use spring.web.resources.static-locations instead.Ackley
is it not spring.web.resources.static-locations instead of spring.resources.static-locations?Changeful
I
8

@Mark Schäfer

Never too late, but add a slash (/) after static:

spring.resources.static-locations=file:/opt/x/y/z/static/

So http://<host>/index.html is now reachable.

Inquiline answered 23/3, 2018 at 18:46 Comment(0)
M
2

To serve from file system

I added spring.resources.static-location=file:../frontend/build in application.properties

index.html is present in the build folder

Use can also add absolute path

spring.resources.static-location=file:/User/XYZ/Desktop/frontend/build

I think similarly you can try adding Dropbox folder path.

Megan answered 9/5, 2018 at 11:21 Comment(0)
J
1

For the current Spring-Boot Version 1.5.3 the parameter is

spring.resources.static-locations

Update I configured

`spring.resources.static-locations=file:/opt/x/y/z/static``

and expected to get my index.html living in this folder when calling

http://<host>/index.html

This did not work. I had to include the folder name in the URL:

http://<host>/static/index.html

Johnsonjohnsonese answered 2/6, 2017 at 10:41 Comment(0)
G
1

FWIW, I didn't have any success with the spring.resources.static-locations recommended above; what worked for me was setting spring.thymeleaf.prefix:

report.location=file:/Users/bill/report/html/
spring.thymeleaf.prefix=${report.location}
Gemoets answered 31/5, 2018 at 20:20 Comment(0)
R
1

Note that WebMvcConfigurerAdapter is deprecated now (see WebMvcConfigurerAdapter). Due to Java 8 default methods, you only have to implement WebMvcConfigurer.

Radiobroadcast answered 15/6, 2018 at 9:31 Comment(0)
J
0

You can place your folder in the root of the ServletContext.

Then specify a relative or absolute path to this directory in application.yml:

spring:
  resources:
    static-locations: file:some_temp_files/

The resources in this folder will be available (for downloading, for example) at:

http://<host>:<port>/<context>/your_file.csv
Jude answered 19/9, 2019 at 16:19 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.