2012-08-22 8 views
12

私はユーザーがファイルをアップロードできるplay 2.0 Javaアプリケーションを作成しています。再生フレームワーク2.0でファイルをストリームとしてアップロードする

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

私は以下のような簡単なコントローラを使用して作業アップロードを作ることができた。これらのファイルは、私はJavaライブラリを使用してアクセスするサードパーティのサービスに保存されている、私はこのAPIで使用するメソッドのシグネチャは次のとおりです。

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(); 
    } 

私の関心は、サーバー上の一時ファイルにクライアントによってアップロードされたすべてのデータは、コントローラの私のuploadFile()メソッドを呼び出しているため、デフォルトでは、このソリューションは、効率的ではないことを遊びの枠組み店です。私はこのように振る舞うサーブレットを書かれていた伝統的なサーブレットアプリケーションで

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

私はどこでも検索されていますし、任意の解決策を見つけることができませんでした。私が見つけた最も近い例はWhy makes calling error or done in a BodyParser's Iteratee the request hang in Play Framework 2.0?ですが、私のニーズに合わせて修正する方法は見つかりませんでした。

この動作を実現する方法はありますか?つまり、クライアントからアップロードされたデータを別のシステムに直接渡すことですか?

ありがとうございました。

答えて

12

私は以下のScalaのコントローラコードを使用して、私のサードパーティのAPIにデータをストリーミングすることができました:

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

UploadFileWorkerがthridパーティのAPIへの呼び出しが含まれて本当に簡単なJavaクラスです。

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

}

私はアクションのパラメータとしてパスを回収することが好ましいだろうが、私はそうすることができていないので、それは完全に完璧ではありません。私はこのように、入力フィールド(とpartName)の名前を更新するjavascriptを追加し、トリックを行います。

+0

これをScalaではなくJavaで実行する方法はありますか? :( – by0

関連する問題