All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.mle.play.streams.Streams.scala Maven / Gradle / Ivy

package com.mle.play.streams

import java.io._
import play.api.libs.iteratee.{Done, Input, Cont, Iteratee}
import java.nio.file.Path
import scala.concurrent.ExecutionContext
import com.mle.storage.StorageSize
import com.mle.storage.StorageInt

/**
 *
 * @author mle
 */
trait Streams {
  //  /**
  //   * http://stackoverflow.com/questions/12066993/uploading-file-as-stream-in-play-framework-2-0
  //   *
  //   * @return an [[InputStream]] and an [[Iteratee]] such that any bytes consumed by the Iteratee are made available to the InputStream
  //   */
  //  def joinedStream()(implicit ec: ExecutionContext): (InputStream, Iteratee[Array[Byte], OutputStream]) = {
  //    val outStream = new PipedOutputStream()
  //    val inStream = new PipedInputStream(outStream)
  //    val iteratee = fromOutputStream(outStream).map(os => {
  //      os.close()
  //      os
  //    })
  //    (inStream, iteratee)
  //  }
  /**
   * http://stackoverflow.com/questions/12066993/uploading-file-as-stream-in-play-framework-2-0
   *
   * @return an [[InputStream]] and an [[Iteratee]] such that any bytes consumed by the Iteratee are made available to the InputStream
   */
  def joinedStream(inputBuffer: StorageSize = 10.megs)(implicit ec: ExecutionContext): (InputStream, Iteratee[Array[Byte], Long]) = {
    val outStream = new PipedOutputStream()
    val bufferSize = math.min(inputBuffer.toBytes.toInt, Int.MaxValue)
    val inStream = new PipedInputStream(outStream, bufferSize)
    val iteratee = closingStreamWriter(outStream)
    (inStream, iteratee)
  }

  /**
   * @return an [[Iteratee]] that writes any consumed bytes to `os`
   */
  def streamWriter(outStreams: OutputStream*)(implicit ec: ExecutionContext): Iteratee[Array[Byte], Long] =
    byteConsumer(bytes => {
      outStreams.foreach(_.write(bytes))
    })

  /**
   * Builds an [[Iteratee]] that writes consumed bytes to all `outStreams`. The streams are closed when the [[Iteratee]] is done.
   *
   * @return an [[Iteratee]] that writes to `outStream`
   */
  def closingStreamWriter(outStreams: OutputStream*)(implicit ec: ExecutionContext): Iteratee[Array[Byte], Long] =
    streamWriter(outStreams: _*).map(bytes => {
      outStreams.foreach(_.close())
      bytes
    })

  /**
   * @param f
   * @return an iteratee that consumes bytes by applying `f` and returns the total number of bytes consumed
   */
  def byteConsumer(f: Array[Byte] => Unit)(implicit ec: ExecutionContext): Iteratee[Array[Byte], Long] =
    Iteratee.fold[Array[Byte], Long](0)((count, bytes) => {
      f(bytes)
      count + bytes.length
    })

  /**
   * @return an [[Iteratee]] that writes any consumed bytes to `os`
   */
  def fromOutputStream(os: OutputStream)(implicit ec: ExecutionContext) =
    Iteratee.fold[Array[Byte], OutputStream](os)((state, data) => {
      state.write(data)
      state
    })

  /**
   * @param file destination file
   * @return an [[Iteratee]] that writes bytes to `file`, keeping track of the number of bytes written
   */
  def fileWriter(file: Path): Iteratee[Array[Byte], Long] = {
    def fromStreamAcc(stream: OutputStream, bytesWritten: Long): Iteratee[Array[Byte], Long] = Cont {
      case [email protected] =>
        stream.close()
        Done(bytesWritten, e)
      case Input.El(data) =>
        stream.write(data)
        fromStreamAcc(stream, bytesWritten + data.length)
      case Input.Empty =>
        fromStreamAcc(stream, bytesWritten)
    }
    val outputStream = new BufferedOutputStream(new FileOutputStream(file.toFile))
    fromStreamAcc(outputStream, 0)
  }

  def fileWriter2(file: Path)(implicit ec: ExecutionContext): Iteratee[Array[Byte], Long] = {
    val outputStream = new BufferedOutputStream(new FileOutputStream(file.toFile))
    closingStreamWriter(outputStream)
  }
}

object Streams extends Streams




© 2015 - 2025 Weber Informatics LLC | Privacy Policy