[英]Streaming large files with play framework and third party API
我正在寫一個播放2應用程序,我正在努力解決文件流問題。 我使用第三方API檢索我的文件,其方法具有以下簽名:
FileMetadata getFile(OutputStream destination, String fileId)
在傳統的Servlet應用程序中,如果我想將內容發送到我的客戶端,我會做類似的事情:
HttpServletResponse resp;
myService.getFile(resp.getOutpuStream, fileId);
我的問題是,在我的Play 2 Controller類中,我無法訪問底層的OuputStream,因此我的控制器方法的最簡單實現是:
public static downloadFile(String id) {
ByteArrayOutputStream baos = new BAOS(...);
myApi.getFile(baos,id); //Load inside temp Array
ByteArrayInputStream bais = new BAIS(baos.toByteArray())
return Ok(bais);
}
它可以工作,但它需要在服務之前將整個內容加載到內存中,因此它不是一個選項(文件可能很大)。
我在考慮一個解決方案,包括:
問題是我不知道是否可能(調用getFile是阻塞所以它需要多個線程與共享OutputStream),也不是它有點過分。
有人遇到過這種問題並找到了解決方案嗎? 我提議的解決方案能解決我的問題嗎
任何見解將不勝感激。
謝謝
編輯1基於kheraud建議我已經設法有一個工作但仍然不完美的解決方案(下面的代碼)。
不幸的是,如果在調用getFile方法期間出現問題,則不會將錯誤發送回客戶端(因為我返回了Ok)並且瀏覽器無限期地等待一個永遠不會出現的文件。
有辦法處理這種情況嗎?
public static Result downloadFile(String fileId {
Thread readerThread = null;
try {
PipedOutputStream pos = new PipedOutputStream();
PipedInputStream pis = new PipedInputStream(pos);
//Reading must be done in another thread
readerThread = new DownloadFileWorker(fileId,pos);
readerThread.start();
return ok(pis);
} catch (Exception ex) {
ex.printStackTrace();
return internalServerError(ex.toString());
}
}
static class DownloadFileWorker extends Thread{
String fileId;
PipedOutputStream pos;
public DownloadFileWorker(String fileId, PipedOutputStream pos) {
super();
this.fileId = fileId
this.pos = pos;
}
public void run(){
try {
myApi.getFile(pos,fileId);
pos.close();
} catch (Exception ex) {
ex.printStackTrace();
}
}
}
編輯2
我找到了一種避免無限加載頁面的方法,只需在工作線程的catch()部分添加一個pos.close即可。 客戶端最終得到一個零KB文件,但我想這比無限等待更好。
Play2 Scala框架中有一些內容: Enumerators
。 這與您的想法非常接近。
您應該查看此文檔頁面以獲取詳細信息
我沒有在Play2 Java API中找到類似的東西,但是查看fw代碼源,你有一個:
public static Results.Status ok(java.io.InputStream content, int chunkSize)
接縫是你正在尋找的方法。 可以在play.mvc.Results
和play.core.j.JavaResults
類中找到該實現。
在游戲中! 郵件列表,最近有一個關於同一主題的討論:
https://groups.google.com/forum/#!topic/play-framework/YunJzgxPKsU/discussion
它包含一個小片段,允許非scala-literates(像我一樣)使用Play!的scala流媒體界面。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.