从Play2 / Scala内存中的MultipartFormData中提取文件 [英] Pulling files from MultipartFormData in memory in Play2 / Scala

查看:232
本文介绍了从Play2 / Scala内存中的MultipartFormData中提取文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



  

> def fileUploader = Action(parse.multipartFormData){request =>
request.body.file(qqfile)。map {picture =>
import java.io.File
val filename = picture.filename $ b $ val contentType = picture.contentType
picture.ref.moveTo(new File(/ tmp,filename) )
Ok(Json.toJson(Map(success - >true)))
} .getOrElse {
Ok(Json.toJson(Map(error - > ;error occured)))
}
}

只处理小文件(< 10MB),我想用casbah把这些文件直接写入Mongo Document或者使用Mongo驱动的GridFS。我知道我可以从磁盘读取保存的文件,但是有没有办法从内存中处理这一切,而不是先缓冲在磁盘上的文件?



建议编写一个自定义BodyParser( http://www.playframework.com/documentation/2.1.0/ScalaFileUpload),但似乎没有任何文档如何去写一个。目前还不清楚从Scaladocs API /实现如何工作。我试图寻找MultiPartFormData源代码来看看它是如何工作的,但我似乎无法在他们的Git仓库中找到它:



https://github.com/playframework/Play20/tree/master/framework / src / play / src / main / scala / play / api / mvc

我搜索了很多,但似乎找不到一个很好的例子。

解决方案

BodyParsers 的c>对象为我们做了很多工作。首先我们需要为 FilePart 写一个处理程序。我假设你想要的文件部分是一个数组[字节]

  def handleFilePartAsByteArray:PartHandler [FilePart [Array [Byte]]] = 
handleFilePart {
case FileInfo(partName,filename,contentType)=>
//将数据写入一个ByteArrayOutputStream
Iteratee.fold [Array [Byte],ByteArrayOutputStream](
new ByteArrayOutputStream()){(os,data)=>
os.write(data)
os
} .mapDone {os =>
os.close()
os.toByteArray
}
}



 multipartFormData(handleFilePartAsByteArray)

然后,为了使用它,在你 Action

  def fileUploader = Action(multipartFormDataAsBytes){request => 
request.body.files foreach {
case FilePart(key,filename,contentType,bytes)=> //做点什么
}
OK(完成)
}



上面代码中的一些类型和方法有点难以找到。这里有一个完整的导入列表,以防你需要它:

  import play.api.mvc.BodyParsers.parse.Multipart。 PartHandler 
import play.api.mvc.BodyParsers.parse.Multipart.handleFilePart
import play.api.mvc.BodyParsers.parse.Multipart.FileInfo
import play.api.mvc.BodyParsers。 parse.multipartFormData
import play.api.mvc.MultipartFormData.FilePart
import play.api.libs.iteratee.Iteratee
import java.io.ByteArrayOutputStream
import play.api。 mvc.BodyParser
import play.api.mvc.MultipartFormData


I'm currently using the following with Play2/Scala using the FileUploader Javascript utility to upload a file to my server:

def fileUploader = Action(parse.multipartFormData) { request =>
  request.body.file("qqfile").map { picture =>
    import java.io.File
    val filename = picture.filename 
    val contentType = picture.contentType
    picture.ref.moveTo(new File("/tmp",filename))
    Ok(Json.toJson(Map( "success" -> "true" )))
  }.getOrElse {
    Ok(Json.toJson(Map( "error" -> "error occured")))
  }
}

I'm only dealing with small files (<10MB) and I want to use casbah to write those files directly into a Mongo Document or GridFS using the Mongo drivers. I realize I could just read the saved file from disk, but is there a way to handle this all from memory without buffering the file on disk first?

The play documentation here recommends writing a custom BodyParser (http://www.playframework.com/documentation/2.1.0/ScalaFileUpload) but there doesn't seem to be any documentation on how to go about writing one. It wasn't clear how the API/implementation worked from the Scaladocs. I tried looking for the MultiPartFormData source code to see how it worked, but I can't seem to find it in their Git repo:

https://github.com/playframework/Play20/tree/master/framework/src/play/src/main/scala/play/api/mvc

I've searched quite a bit, but can't seem to find a good example.

解决方案

Untested The Multipart object of the BodyParsers does a lot of work for us. The first thing we need to do write a handler for the FilePart. I assume here that you want the file parts an Array[Byte].

def handleFilePartAsByteArray: PartHandler[FilePart[Array[Byte]]] =
  handleFilePart {
    case FileInfo(partName, filename, contentType) =>
      // simply write the data to the a ByteArrayOutputStream
      Iteratee.fold[Array[Byte], ByteArrayOutputStream](
        new ByteArrayOutputStream()) { (os, data) =>
          os.write(data)
          os
        }.mapDone { os =>
          os.close()
          os.toByteArray
        }
  }

The next step is to define your body parser:

def multipartFormDataAsBytes:BodyParser[MultipartFormData[Array[Byte]]] = 
  multipartFormData(handleFilePartAsByteArray)

Then, in order to use it, specify it at you Action:

def fileUploader = Action(multipartFormDataAsBytes) { request =>
  request.body.files foreach {
    case FilePart(key, filename, contentType, bytes) => // do something
  }
  Ok("done")
}

Some types and methods in the above pieces of code are a bit hard to find. Here is a complete list of imports in case you need it:

import play.api.mvc.BodyParsers.parse.Multipart.PartHandler
import play.api.mvc.BodyParsers.parse.Multipart.handleFilePart
import play.api.mvc.BodyParsers.parse.Multipart.FileInfo
import play.api.mvc.BodyParsers.parse.multipartFormData
import play.api.mvc.MultipartFormData.FilePart
import play.api.libs.iteratee.Iteratee
import java.io.ByteArrayOutputStream
import play.api.mvc.BodyParser
import play.api.mvc.MultipartFormData

这篇关于从Play2 / Scala内存中的MultipartFormData中提取文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆