Uploading files from Ionic 4 / Cordova to Minio / S3

In the previous post we played with Minio, a S3 compatible server, and wrote a Java application that uploads a file to the server. And in an earlier post we had a look at an example that sends pictures from an Ionic / Cordova application to a Spring Boot server.

In this blog we will do a combination of these two posts and create an example that sends pictures from an Ionic / Cordova application directly to a Minio server.

Minio wrote a JavaScript client library that works with Minio and S3 servers. The primary usage of this library is for Node.js applications, but it also works in the browser. But that's not the way you should use this, because a client needs to know the keys to send requests to a S3 compatible server and storing these keys on the client is considered to be a security risk.

What an application should use instead are pre-signed URLs. This is not a Minio specific feature, Amazon S3 supports this as well. A pre-signed URL is like a one time usage key that allows a client to upload or fetch files from a S3 compatible server without having ecurity credentials with the service.

Flow of a connection with pre-signed URLs.

The client sends a request (1) to a server that creates pre-signed URLs. This service can be implemented in any server side framework. For our example we will write this as a Spring Boot server. The service needs to know the security credentials for the Minio server (keys) to be able to create pre-signed URLs. The service should first check if the client has the proper permissions to upload or fetch files from the server. Then it makes a connection (2) to Minio (or S3) to request a pre-signed URL and returns this URL back to the client. A pre-signed URL can be either used for uploading or for fetching files. In our example this will be an URL that allows the client to upload a file. The client can now directly connect (3) to the Minio server with this URL and either upload or fetch a file.

Before the app is able to upload the picture, it needs to fetch the pre-signed URL. For that the application calls the method fetchPresignUrl. This method sends a HTTP GET request to our Spring Boot server which is listening on the URL /getPreSignUrl and returns the pre-signed URL. After the app received the pre-signed URL it will initiate a PUT request to this URL with the binary data in the body. This PUT request will directly connect to the Minio server and store the file on the server.

Next we create a RestController with one handler that creates and returns pre-signed URLs. We inject the MinioClient bean and call the operation presignedPutObject to request a pre-signed URL from the Minio server.

In the @PostConstruct method the application makes sure that the bucket with the name uploads exists. When the application requests a pre-signed URL, it must provide a bucket name, a file name and the expiration time of the URL in seconds. For this example the pre-sign URL will be valid for 60 seconds, after that the client is no longer able to use this URL.

To test the setup we have to start the Minio and our Spring Boot server (mvn spring-boot:run). Then we have to deploy the Ionic app to a real device or start it on an emulator. You should now be able to upload pictures from the app to the Minio server. If there is a problem check the security credentials and endpoint address for the Minio server in the application.yml file and make sure that the Spring Boot server and the Ionic app on the device/emulator can connect to the Minio server.

As mentioned before this will not only work with a Minio server you can use the same Spring Boot application with Amazon S3 as well. All you need to do is configuring the keys you get from Amazon and use the correct endpoint address (S3 Endpoints).