在不使用gridFSBodyParser(gridFS)的情况下以非阻塞方式上载文件

时间:2014-05-02 13:29:07

标签: playframework-2.2 reactivemongo

插件play-reactivemongo提供了一种上传文件的简便方法:

def upload = Action(gridFSBodyParser(gridFS)) { request =>
  val futureFile: Future[ReadFile[BSONValue]] = request.body.files.head.ref
  futureFile.map { file =>
    // do something
    Ok
  }.recover { case e: Throwable => InternalServerError(e.getMessage)  }
}

不幸的是,这个解决方案不适合我,因为:

  • 我希望只有我的DAO层依赖于reactive-mongo。
  • 我只有在用户通过身份验证(使用SecureSocial)并使用某些用户属性作为检查和元数据时才需要保存文件。
  • 如果没有用户通过身份验证,则根本不应解析请求正文(另请参阅this question)。

这将是一线

def upload = SecuredAction { request =>
  val user = request.user
  val enumerator = an enumrator from the body parsing ???
  myDAO.saveFile(user, enumerator)

object myDAO {
  def saveFile(user:User, enumerator:Enumerator[Array[Byte]]) = {
    ...
    val fileToSave = DefaultFileToSave(...)
    gridfs.save(enumerator, fileToSave)
    ...
  } 
}

不幸的是,似乎没有办法从解析请求体中获取枚举器。唯一的方法似乎是为Action提供一个解析器和一个Iteratee,它将被正在被解析的主体提供。

我无法弄清楚如何以反应方式实现它(不使用临时文件或将主体存储在内存中)。它有可能吗?

1 个答案:

答案 0 :(得分:2)

实际上,您可能根本不考虑使用girdFS内置解析器:

val gfs = new GridFS(db)

// the controller method, Authenticated here is custom object extending ActionBuilder 
def upload = Authenticated.async(parse.multipartFormData) { request =>
  ...
  request.body.file("photo") match {
    // handle error cases
    ...
    case Some(photo) =>
      val fileToSave = DefaultFileToSave(photo.filename, photo.contentType)
      // here some more operations, basically you don't need the and need only photo.ref.file
      val enumerator = Enumerator(Image(photo.ref.file).fitToWidth(120).write)
      gfs.save(enumerator, fileToSave) map {
        //handle responses and stuff
        ...
      }
    }
  }
}