code: private PutObjectResult putObjectUsingInstructionFile(
          PutObjectRequest putObjectRequest) {
          final File fileOrig = putObjectRequest.getFile();
          final InputStream isOrig = putObjectRequest.getInputStream();
          final PutObjectRequest putInstFileRequest = putObjectRequest.clone()
                                                                      .withFile(null)
                                                                      .withInputStream(null)
              ;
          putInstFileRequest.setKey(putInstFileRequest.getKey() + DOT
                                    + DEFAULT_INSTRUCTION_FILE_SUFFIX);
          // Create instruction
          ContentCryptoMaterial cekMaterial = createContentCryptoMaterial(putObjectRequest);
          // Wraps the object data with a cipher input stream; note the metadata
          // is mutated as a side effect.
          PutObjectRequest req = wrapWithCipher(putObjectRequest, cekMaterial);
          // Put the encrypted object into S3
          final PutObjectResult result;
          try {
              result = s3.putObject(req);
          } finally {
              cleanupDataSource(putObjectRequest, fileOrig, isOrig,
                                req.getInputStream(), log);
          }
          // Put the instruction file into S3
          s3.putObject(updateInstructionPutRequest(putInstFileRequest,
                                                   cekMaterial));
          // Return the result of the encrypted object PUT.
          return result;
      }
docs: Puts an encrypted object into S3, and puts an instruction file into S3.
  Encryption info is stored in the instruction file.
  
  @param putObjectRequest
  The request object containing all the parameters to upload a
  new object to Amazon S3.
  @return A {@link PutObjectResult} object containing the information
  returned by Amazon S3 for the new, created object.