I'm working on a website that deals with a lot of images. Users will have the ability to upload images. Images would be hosted on a separate remote Nginx server. What is the best way to create directories and upload images to the remote server? Would SSH be a viable option? anything better?

The web application is created with Spring Boot

1 Answers

1
Paul Warren On Best Solutions

SSH won't really do anything to help you share or sync files across a network.

Based on your tag (linux) I suspect you could install the nfs-kernel-server on your "remote" server. Network FileSystem (NFS) allows you to share directories from one OS to another across a network. This will allow you to share a directory from your remote server with your Spring Boot server.

You can follow these instructions to set up your NFS server.

You can then mount that remote directory on your Spring Boot server with:

$ NFS_SERVER="<your remote server>:/<your exported directory>"
$ sudo mount -t nfs "${NFS_SERVER}" /mnt

Reading and writing files to /mnt will actually be reading and writing them to the directory on your remote server. So, all you need to do then is make your Spring Boot app read and write to /mnt.

You could also look at the community project Spring Content. This project is an abstraction over Storage and provides implementations for a range of Storage types including the good old Filesystem so it is ideal for your use case and will simplify your Spring application code by removing the need to code file handling controllers and services yourself.

Adding it would look something like this:

pom.xml (assuming maven).

    <!-- Java API -->
    <!-- just change this depdendency if you want to store somewhere else -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-fs-boot-starter</artifactId>
        <version>0.8.0</version>
    </dependency>
    <!-- REST API -->
    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>spring-content-rest-boot-starter</artifactId>
        <version>0.8.0</version>
    </dependency>

StoreConfig.java

@Configuration
@EnableFilesystemStores
@Import(RestConfiguration.class)
public class StoreConfig {

    @Bean
    FileSystemResourceLoader fileSystemResourceLoader() throws IOException {
        return new FileSystemResourceLoader(new File("/mnt").getAbsolutePath());
    }

}

FileStore.java

  @StoreRestResource(path="files")
  public interface FileStore extends Store<String> {
  }

And that's it. The FileStore is essentially a generic Spring ResourceLoader. The spring-content-fs-boot-starter dependency will cause Spring Content to inject a filesystem-based implementation of the FileStore interface so you don't need to worry about implementing it yourself. Moreover, the spring-content-rest-boot-starter dependency will make Spring Content also inject an implementation of an @Controller that forwards HTTP requests onto the methods of the FileStore.

All up, you will now have a fully functional (POST, PUT, GET, DELETE) REST-based file service at /files that will use your FileStore to retrieve (and store) files in /mnt; i.e. on your remote NFS server.

So:

curl -F [email protected]/path/to/local/an-image.jpg /files/some-directory/an-image.jpg

will upload an-image.jpg and store it in /mnt/ on your server.

GET /files/some-directory/an-image.jpg

will download an-image.jpg again.

HTH

The injected controller also supports video streaming too, in case that is useful.

If you wish to record additional metadata about the files your users upload then you can also associate content with Spring Data entities (that can be used to record this additional metadata). You can read more about that here.

HTH