title: Upload Files directly to S3 chunk-by-chunk using Play Scala using Iteratees
body: <p>I have tried in vain to upload files directly to s3 using Iteratees. I am still new to functional programming, and finding it hard to piece together some working code.</p>
  
  <p>I have written an iteratee which process chunks of the uploaded file and sends them to S3. The upload fails at the end with an error.</p>
  
  <p>Please help me fix this.</p>
  
  <p>Below is the code I came up with</p>
  
  <p>Controller Handler</p>
  
  <pre><code>  def uploadFile = Action.async(BodyParser(rh =&gt; S3UploadHelper("bucket-name").s3Iteratee() ))  { implicit request =&gt;
      Future {
        if(uploadLogger.isInfoEnabled) uploadLogger.info(s"Contents of Uploaded file :: \n " + request.body)
        Ok(views.html.index("File uploaded"))
      }
    }
  </code></pre>
  
  <p>Helper Class</p>
  
  <pre><code>case class S3UploadHelper(bucket: String, key: String = UUID.generate()) {
  
    private val AWS_ACCESS_KEY = ""
    private val AWS_SECRET_KEY = ""
    private val yourAWSCredentials = new BasicAWSCredentials(AWS_ACCESS_KEY, AWS_SECRET_KEY)
    val amazonS3Client = new AmazonS3Client(yourAWSCredentials)
  
  
    private val initRequest = new InitiateMultipartUploadRequest(bucket, key)
    private val initResponse = amazonS3Client.initiateMultipartUpload(initRequest)
    val uploadId = initResponse.getUploadId
  
    val uploadLogger = Logger("upload")
  
    def s3Iteratee(etags: Seq[PartETag] = Seq.empty[PartETag]): Iteratee[Array[Byte], Either[Result, CompleteMultipartUploadResult]] = Cont {
      case in: El[Array[Byte]] =&gt;
        // Retrieve the part that has not been processed in the previous chunk and copy it in front of the current chunk
        val uploadRequest = new UploadPartRequest()
          .withBucketName(bucket)
          .withKey(key)
          .withPartNumber(etags.length + 1)
          .withUploadId(uploadId)
          .withInputStream(new ByteArrayInputStream(in.e))
          .withPartSize(in.e.length)
        if(uploadLogger.isDebugEnabled) uploadLogger.debug("&gt;&gt; " + String.valueOf(in.e))
        val etag = Future { amazonS3Client.uploadPart(uploadRequest).getPartETag }
        etag.map(etags :+ _)
        Await.result(etag, 1.seconds)
        s3Iteratee(etags)
      case in @ Empty =&gt; s3Iteratee(etags)
      case in @ EOF =&gt;
        import scala.collection.JavaConversions._
        val compRequest = new CompleteMultipartUploadRequest(bucket, key, uploadId, etags.toList)
        val result = amazonS3Client.completeMultipartUpload(compRequest)
        Done(Right(result), in)
      case in =&gt; s3Iteratee(etags)
    }
  
  }
  </code></pre>
  
  <p>Although the Iteratee seems to work and I am able to process the file chunk by chunk, the upload fails with a weird error. Here are the logs</p>
  
  <pre><code>[debug] upload - &gt;&gt; [B@1df9048d
  [debug] upload - &gt;&gt; [B@152dcf59
  [debug] upload - &gt;&gt; [B@7cfeb0d8
  [debug] upload - &gt;&gt; [B@136844c5
  [debug] upload - &gt;&gt; [B@16f41590
  [debug] upload - &gt;&gt; [B@6dd85710
  [debug] upload - &gt;&gt; [B@64294203
  [debug] upload - &gt;&gt; [B@35366c2f
  [debug] upload - &gt;&gt; [B@358a78c
  [debug] upload - &gt;&gt; [B@2c171020
  [debug] upload - &gt;&gt; [B@20076fb
  [debug] upload - &gt;&gt; [B@4d13580
  [debug] upload - &gt;&gt; [B@42738651
  [debug] upload - &gt;&gt; [B@5671082f
  [debug] upload - &gt;&gt; [B@57c70bb4
  [debug] upload - &gt;&gt; [B@4154394f
  [debug] upload - &gt;&gt; [B@4f93cf15
  [debug] upload - &gt;&gt; [B@4bac523f
  [debug] upload - &gt;&gt; [B@eaec52e
  [debug] upload - &gt;&gt; [B@6ed00bf5
  [debug] upload - &gt;&gt; [B@3f6a8a5d
  [debug] upload - &gt;&gt; [B@16fe1a25
  [debug] upload - &gt;&gt; [B@6e813a61
  [debug] upload - &gt;&gt; [B@e01be7
  [debug] upload - &gt;&gt; [B@6bb351c4
  [debug] upload - &gt;&gt; [B@dfa51a5
  [debug] upload - &gt;&gt; [B@6acf2049
  [debug] upload - &gt;&gt; [B@6a7021d4
  [debug] upload - &gt;&gt; [B@1b3c602f
  [debug] upload - &gt;&gt; [B@44146d94
  [debug] upload - &gt;&gt; [B@574ac037
  [debug] upload - &gt;&gt; [B@3cdf258b
  [debug] upload - &gt;&gt; [B@441a0727
  [debug] upload - &gt;&gt; [B@2385aafd
  [debug] upload - &gt;&gt; [B@224f9dc2
  [debug] upload - &gt;&gt; [B@6779077d
  [debug] upload - &gt;&gt; [B@734e178a
  [debug] upload - &gt;&gt; [B@7d92895c
  [debug] upload - &gt;&gt; [B@23edaaa1
  [debug] upload - &gt;&gt; [B@c00134e
  [debug] upload - &gt;&gt; [B@ff1a703
  [error] play - Cannot invoke the action, eventually got an error: Status Code: 400, AWS Service: Amazon S3, AWS Request ID: 98h72s0EBA7653AD, AWS Error Code: MalformedXML, AWS Error Message: The XML you provided was not well-formed or did not validate against our published schema, S3 Extended Request ID: R7e44g8oRy5b4xd7MU++atibwrBSRFezeMxNCXE38gyzcwci5Zf
  [error] application - 
  
  ! @6k2maob49 - Internal server error, for (POST) [/v1/file_upload] -&gt;
  
  play.api.Application$$anon$1: Execution exception[[AmazonS3Exception: The XML you provided was not well-formed or did not validate against our published schema]]
          at play.api.Application$class.handleError(Application.scala:296) ~[play_2.10-2.3.2.jar:2.3.2]
          at play.api.DefaultApplication.handleError(Application.scala:402) [play_2.10-2.3.2.jar:2.3.2]
          at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.10-2.3.2.jar:2.3.2]
          at play.core.server.netty.PlayDefaultUpstreamHandler$$anonfun$3$$anonfun$applyOrElse$4.apply(PlayDefaultUpstreamHandler.scala:320) [play_2.10-2.3.2.jar:2.3.2]
          at scala.Option.map(Option.scala:145) [scala-library.jar:na]
  Caused by: com.amazonaws.services.s3.model.AmazonS3Exception: The XML you provided was not well-formed or did not validate against our published schema
          at com.amazonaws.http.AmazonHttpClient.handleErrorResponse(AmazonHttpClient.java:556) ~[aws-java-sdk-1.3.11.jar:na]
          at com.amazonaws.http.AmazonHttpClient.executeHelper(AmazonHttpClient.java:289) ~[aws-java-sdk-1.3.11.jar:na]
          at com.amazonaws.http.AmazonHttpClient.execute(AmazonHttpClient.java:170) ~[aws-java-sdk-1.3.11.jar:na]
          at com.amazonaws.services.s3.AmazonS3Client.invoke(AmazonS3Client.java:2723) ~[aws-java-sdk-1.3.11.jar:na]
          at com.amazonaws.services.s3.AmazonS3Client.completeMultipartUpload(AmazonS3Client.java:1964) ~[aws-java-sdk-1.3.11.jar:na]
  </code></pre>