1. Overview

In this tutorial, we're going to look at how we can access files as Resources using Spring. In the end, the approaches detailed here will help us when reading a file from the Maven resources folder or accessing a file from the file system.

2. Inject File As Resource

Firstly, we'll inject a file as Resource using the @Value annotation. The value attribute of @Value must be the path of the file. Additionally, we'll add a prefix to specify the resource type:

@Component
public class AsDependencyGreetingService {

    @Value("classpath:fileasresource/hello.txt")
    private Resource greeting;

    public void greet() throws IOException {
        final InputStreamReader reader = new InputStreamReader(greeting.getInputStream());
        System.out.println(FileCopyUtils.copyToString(reader));
    }
}

Here, we have the greeting variable that holds our file as a Resource. Note that we're defining the file path as "classpath:fileasresource/hello.txt". So we must have a hello.txt file under the fileasresource folder. Moreover, the fileasresource folder must be on the classpath, since we have the classpath prefix. In our case, hello.txt resides under the Maven resources folder -/resources/fileasresource/hello.txt. This works because the Maven resources folder is on the classpath with the default Maven settings. Then in the greet method, we're reading the file content using its InputStream. 

This approach is preferable when the file path is static and won't change during the lifetime of an application.

3. Access File with ResourceLoader

When we determine the file path through a dynamic process, injecting a file with @Value won't work. Instead, we'll use the ResourceLoader class to read a file and get its Resource handle. The ResourceLoader interface - which Spring's ApplicationContext also extends - has a central place when loading resources.

@Component
public class ResourceLoaderGreetingService {

    private final ResourceLoader resourceLoader;

    @Autowired
    public ResourceLoaderGreetingService(ResourceLoader resourceLoader) {
        this.resourceLoader = resourceLoader;
    }

    public void greet() throws IOException {
        final Resource resource = resourceLoader.getResource("classpath:fileasresource/hello.txt");
        final InputStreamReader reader = new InputStreamReader(resource.getInputStream());
        System.out.println(FileCopyUtils.copyToString(reader));
    }
}

In this example, we're declaring ResourceLoader as a dependency, and Spring autowires it for us. Moreover, we don't need to define a ResourceLoader bean, since the ApplicationContext bean is also a ResourceLoader. In the greet method, we're calling the ResourceLoader.getResource method with the file path. Similar to the previous example, we're prefixing the file path with the resource type - classpath. Then Spring reads the file and returns a Resource instance back.

Now, let's access a file on the file system instead of the classpath:

final Resource resource = resourceLoader.getResource("file:/home/.../fileasresource/hello.txt");

Here, we're accessing hello.txt using an absolute path and the file prefix.

4. Access File Manually with Resource

Lastly, we'll look at how we can access a file by directly using the Resource interface:

@Component
public class ResourceGreetingService {

    public void greet() throws IOException {
        final Resource resource = new ClassPathResource("fileasresource/hello.txt");
        final InputStreamReader reader = new InputStreamReader(resource.getInputStream());
        System.out.println(FileCopyUtils.copyToString(reader));
    }
}

Here, we're creating an instance of ClassPathResource using the file path - fileasresource/hello.txt. Unlike the previous examples, we mustn't add the classpath prefix to the file path since ClassPathResource implicitly sets the resource type. If we add the prefix despite this, the file can't be found.

5. Summary

In this tutorial, we've looked at how we can access files as resources using Spring. We started with a declarative approach and used the @Value annotation to inject a file as a dependency. Then we examined other approaches that give us more control, using the ResourceLoader and Resource interfaces.

Lastly, check out the source code for all examples in this tutorial over on Github.