2

插件 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 层依赖于响应式 mongo。
  • 仅当用户经过身份验证(使用 SecureSocial)并使用某些用户的属性作为检查和元数据时,我才需要保存文件。
  • 如果没有用户通过身份验证,则根本不应解析请求正文(另请参阅此问题)。

这将是大势所趋

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,它将与被解析的主体一起提供。

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

4

1 回答 1

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
        ...
      }
    }
  }
}
于 2014-05-15T08:44:58.073 回答