Using Play-S3 plugin to upload files to Amazon.

One of the most common task in applications around the world is the file upload. And, nowadays, instead of store these files in our server, is quite normal send them to Amazon S3. In this post let’s see how to use the Play-S3 plugin for a Play application using Java.

The first problem is that this plugin only has a Scala version. What are you gonna do? Are you going to implement everything again? It seems a little bit over… As we has already discussed in another post, your Play project is Java and Scala, together! Let’s mix both languages and take advantage of this plugin.

The first thing you have to do is to add the Play-s3 as a dependency in your build.sbt file.

    libraryDependencies ++= Seq(
      javaJdbc,
      cache,
      javaJpa,
      "org.hibernate" % "hibernate-entitymanager" % "3.6.9.Final",
       "mysql" % "mysql-connector-java" % "5.1.20",
       "org.mindrot" % "jbcrypt" % "0.3m",
       "ws.securesocial" %% "securesocial" % "2.1.3",
       "nl.rhinofly" %% "play-s3" % "3.3.5"
)

Now you have to configure your access and secret key in order to enable the upload of files to S3. This configuration, as usual, is placed in the *.conf file of your application.

  aws.accessKeyId="accessKeyHere"
  aws.secretKey="secretKeyHere"

Previously, you could get these keys from your root account in Amazon but, for security reasons, a few weeks ago they started to force you to follow a new process to configure your keys. You have to use the Identity and Access Management (IAM) and create your keys. They suggest that you create a pair of keys for each kind of user that your application has. The choice is yours 🙂

Now let’s take a look in the code necessary to upload a file.

    val result:Future[Unit] = bucket + BucketFile("pdfs/yourfile.pdf",
      "application/pdf",IOUtils.toByteArray(new FileInputStream(pdfFile)),Some(PUBLIC_READ))

There are a two important objects here. Bucket and the BucketFile. The first is needed to identify which folder(bucket) contains all your uploaded files from your current application. It is easy to create this object.

    private val bucket = S3("youpet")

Probably you will create one bucket per application.

The BucketFile is just a wrapper with all information needed about your file being uploaded. The last parameter is a little bit important. It is recommended to pass which roles this file has. Here we are saying that everyone can read(download). All this code can be encapsulated in a Scala class that can be used from your Java code :).

    object AmazonS3 {
      private val bucket = S3("youpet")

      def upload(folder: String, file: File,fileName:String): WaitingForS3 = {
        val timestampedName = FilenameUtils.getBaseName(fileName)+"_"+System.currentTimeMillis()+"."+FilenameUtils.getExtension(fileName)
        val s3Url = bucket.url(s"${folder}/${timestampedName}")

        val result:Future[Unit] = bucket + BucketFile(s"${folder}/${timestampedName}",
          extractMimeType(fileName),
          IOUtils.toByteArray(new FileInputStream(file)),Some(PUBLIC_READ))

        result.map { unit =>
          Logger.debug(s"Enviou o arquivo $s3Url")
        }.recover {
          case S3Exception(status, code, message, originalXml) => Logger.info("Error: " + message)
        }

        new WaitingForS3(s3Url,result)
      }
    }

This same code is available here. Feel free to copy and use in your projects :). Of course you could use all these Scala classes from your Java code directly but, in this case there are “functions as parameters” and “case classes” that are hard to translate to Java code. It is better isolate this code in a Adapter class and only expose a simple method to your Java side.

That is it! Upload your files to S3 and just have to deal with the links of your uploaded files :). It is easy to maintain and you gain, as a bonus, things like cache out of the box :).

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s