Upload to S3 with resourceLoader - Spring Boot

I'm trying to upload a file to my s3 bucket without AWS SDK, using only Spring cloud with resourceLoader bean.

I have this code:

private fun uploadS3(awsFileName: String, content: String): String {
    val writableResource = resourceLoader.getResource(awsFileName) as WritableResource
    writableResource.outputStream.use { it.write(content.toByteArray()) }
    return writableResource.url.toString()
}

My application.yml has this configuration:

 cloud:
  aws:
    credentials:
      accessKey: XXXXX
      secretKey: XXXXX
      instanceProfile: false
    region:
      static: us-east-1
      auto: false
  s3:
    default-bucket: XXXXXX

My Spring Boot version is:

springBootVersion = '2.0.2.RELEASE'

But all I get is this error:

There is no EC2 meta data available, because the application is not running in the EC2 environment. Region detection is only possible if the application is running on a EC2 instance

And I just don't know how to solve this issue. Please, help me!

Upvotes: 1

Views: 4044

Answers (1)

Paul Warren
Paul Warren

Reputation: 2479

You could use Spring Content S3 which uses the SimpleStorageResourceLoader underneath the covers.

Add the following dependencies to your pom.xml

pom.xml

    <dependency>
        <groupId>com.github.paulcwarren</groupId>
        <artifactId>content-s3-spring-boot-starter</artifactId>
        <version>0.1.0</version>
    </dependency>

Add the following configuration that creates a SimpleStorageResourceLoader bean:

    @Autowired
    private Environment env;

    public Region region() {
        return Region.getRegion(Regions.fromName(env.getProperty("AWS_REGION")));
    }

    @Bean
    public BasicAWSCredentials basicAWSCredentials() {
        return new BasicAWSCredentials(env.getProperty("AWS_ACCESS_KEY_ID"), env.getProperty("AWS_SECRET_KEY"));
    }

    @Bean
    public AmazonS3 client(AWSCredentials awsCredentials) {
        AmazonS3Client amazonS3Client = new AmazonS3Client(awsCredentials);
        amazonS3Client.setRegion(region());
        return amazonS3Client;
    }

    @Bean
    public SimpleStorageResourceLoader simpleStorageResourceLoader(AmazonS3 client) {
        return new SimpleStorageResourceLoader(client);
    }

Create a "Store":

S3Store.java

public interface S3Store extends Store<String> {
}

Autowire this store where you need to upload resource:

@Autowired
private S3Store store;

WritableResource r = (WritableResource)store.getResource(getId());
InputStream is = // your input stream
OutputStream os = r.getOutputStream();
IOUtils.copy(is, os);
is.close();
os.close();

When your application starts it will see the dependency on spring-content-s3 and your S3Store interface and inject an implementation for you therefore you don't need to worry about implementing it yourself.

HTH

Upvotes: 2

Related Questions