2012-08-22 32 views
12

Estoy escribiendo una aplicación java 2.0 que permite a los usuarios subir archivos. Estos archivos se almacenan en un servicio de terceros que accede mediante una biblioteca de Java, el método que utilizo en este API tiene la siguiente firma:Cargando archivos como transmisión en play framework 2.0

void store(InputStream stream, String path, String contentType) 

He conseguido hacer cargas de trabajo con el siguiente controlador simple:

public static Result uploadFile(String path) { 
    MultipartFormData body = request().body().asMultipartFormData(); 
    FilePart filePart = body.getFile("files[]"); 
    InputStream is = new FileInputStream(filePart.getFile()) 
    myApi.store(is,path,filePart.getContentType()); 
    return ok(); 
    } 

mi preocupación es que esta solución no es eficaz, ya que por defecto las tiendas marco de juego todos los datos cargados por el cliente en un archivo temporal en el servidor a continuación, llama mi método uploadfile() en el controlador.

En una aplicación tradicional servlet habría escrito un servlet comportarse de esta manera:

myApi.store(request.getInputStream(), ...) 

He estado buscando por todos lados y no encontrar ninguna solución. El ejemplo más cercano que encontré es Why makes calling error or done in a BodyParser's Iteratee the request hang in Play Framework 2.0? pero no encontré cómo modificarlo para adaptarlo a mis necesidades.

¿Hay alguna forma en el juego2 para lograr este comportamiento, es decir, hacer que los datos cargados por el cliente pasen directamente por la aplicación web a otro sistema?

Gracias.

Respuesta

12

he sido capaz de transmitir datos a mi API de terceros mediante el siguiente código de controlador de Scala:

def uploadFile() = 
    Action(parse.multipartFormData(myPartHandler)) 
    { 
     request => Ok("Done") 
    } 

def myPartHandler: BodyParsers.parse.Multipart.PartHandler[MultipartFormData.FilePart[Result]] = { 
     parse.Multipart.handleFilePart { 
      case parse.Multipart.FileInfo(partName, filename, contentType) => 
      //Still dirty: the path of the file is in the partName... 
      String path = partName; 

      //Set up the PipedOutputStream here, give the input stream to a worker thread 
      val pos:PipedOutputStream = new PipedOutputStream(); 
      val pis:PipedInputStream = new PipedInputStream(pos); 
      val worker:UploadFileWorker = new UploadFileWorker(path,pis); 
      worker.contentType = contentType.get; 
      worker.start(); 

      //Read content to the POS 
      Iteratee.fold[Array[Byte], PipedOutputStream](pos) { (os, data) => 
       os.write(data) 
       os 
      }.mapDone { os => 
       os.close() 
       Ok("upload done") 
      } 
     } 
    } 

El UploadFileWorker es una clase Java muy simple que contiene la llamada a la API thrid-partido .

public class UploadFileWorker extends Thread { 
String path; 
PipedInputStream pis; 

public String contentType = ""; 

public UploadFileWorker(String path, PipedInputStream pis) { 
    super(); 
    this.path = path; 
    this.pis = pis; 
} 

public void run() { 
    try { 
     myApi.store(pis, path, contentType); 
     pis.close(); 
    } catch (Exception ex) { 
     ex.printStackTrace(); 
     try {pis.close();} catch (Exception ex2) {} 
    } 
} 

}

No es completamente perfecto, porque yo hubiera preferido para recuperar la ruta como un parámetro de la acción, pero no he sido capaz de hacerlo. Por lo tanto, he agregado una pieza de javascript que actualiza el nombre del campo de entrada (y por lo tanto, el nombre de la pieza) y hace el truco.

+0

¿Hay alguna forma de hacerlo en Java en lugar de en Scala? :( – by0

Cuestiones relacionadas