2013-02-23 11 views
7

Attualmente sto usando il seguente con Play2/Scala utilizzando l'utilità FileUploader Javascript per caricare un file al mio server:Tirando file da MultipartFormData nella memoria in Play2/Scala

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"))) 
    } 
} 

Sono solo trattare con piccoli file (< 10 MB) e voglio usare la casbah per scrivere quei file direttamente in un documento Mongo o GridFS usando i driver Mongo. Mi rendo conto che potrei semplicemente leggere il file salvato dal disco, ma esiste un modo per gestirlo tutto dalla memoria senza prima eseguire il buffering del file sul disco?

La documentazione di gioco qui consiglia di scrivere un BodyParser personalizzato (http://www.playframework.com/documentation/2.1.0/ScalaFileUpload) ma non sembra esserci alcuna documentazione su come procedere per scriverne uno. Non era chiaro come l'API/implementazione funzionasse dagli Scaladoc. Ho provato a cercare il codice sorgente MultiPartFormData per vedere come funzionava, ma non riesco a trovare nel loro Git repo:

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

Ho cercato un po ', ma non riesco per trovare un buon esempio.

+1

Il parser corpo 'multipartFormData' può essere trovato qui: https://github.com/playframework/Play20/blob/2.1.0/framework/ src/play/src/main/Scala/play/api/MVC/ContentTypes.scala # L541 – EECOLOR

risposta

12

testato La Multipart oggetto della BodyParsers fa un sacco di lavoro per noi. La prima cosa che dobbiamo fare è scrivere un gestore per lo FilePart. Presumo qui che si desidera il file parti un 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 
     } 
    } 

Il passo successivo è quello di definire il vostro corpo parser:

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

Poi, al fine di utilizzarlo, specificarlo voi al Action:

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

Alcuni tipi e metodi i pezzi di codice di cui sopra sono un po 'difficili da trovare. Ecco un elenco completo delle importazioni in caso di necessità:

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