2014-11-03 327 views
0

我想創建一個下載和上傳大文件的應用程序,所以我不想將文件內容存儲在內存中。用spring mvc流式傳輸大文件

在MVC控制器端我使用一個轉換爲/從InputStream中

@Override 
public InputStream read(Class<? extends InputStream> clazz, HttpInputMessage inputMessage) throws IOException, 
     HttpMessageNotReadableException { 
    return inputMessage.getBody(); 
} 

@Override 
public void write(InputStream t, MediaType contentType, HttpOutputMessage outputMessage) throws IOException, 
     HttpMessageNotWritableException { 

    try { 
     IOUtils.copy(t, outputMessage.getBody()); 
    } finally { 
     IOUtils.closeQuietly(t); 
    } 
} 

這非常適用於服務器端的HTTP消息轉換器。

在客戶端(RestTemplate)一側,我嘗試使用相同的轉換器,但我得到了一個異常,該流已關閉(可能在請求完成時關閉)。

客戶端代碼:

ResponseEntity<InputStream> res = rest.getForEntity(url, InputStream.class); 
// res.getBody() is closed 

我也試着輸入流複製到緩衝區中,並創建一個新的ByteArrayInputStream的,並將其返回到客戶端RestTemplate和它的工作很好,但它確實要求數據將被讀入內存中,這不符合我的要求。

我的問題是如何保持流打開,直到我處理它,而無需將它全部讀入內存/文件?

任何想法將不勝感激。

問候,吉文

+1

你需要輸入和輸出,而不實際保存任何東西,這個頁面我會認爲包含這樣做的大多數方法:http://stackoverflow.com/questions/43157/easy-way-to-write-contents -of-a-java-inputstream-to-an-outputstream – mwarren 2014-11-03 11:44:51

+0

此解決方案的問題在於,在消息轉換器中,我不知道如何處理該文件。將它保存到一個文件?保存到數據庫?等等,只有客戶端知道如何處理它。 – shayma 2014-11-03 12:44:44

回答

0

據我所知,RestTemplate的getForEntity()不是獲取InputStream的合適方法。這對於轉換實體類和從實體類轉換來說是一種方便,所以推測這就是你的問題所在。

由於您習慣了HttpInputMessage,您爲什麼不在客戶端使用HttpInputMessage.getBody()?它爲你提供了一個很好的InputStream,它可以直接傳遞給OutputStream,比如HttpServletResponse.getOutputStream()。

+0

轉換器本身並不知道該如何處理該文件,只有通話後的代碼知道。我可以將它放入臨時文件並返回文件的FileInputStream,但效率不高。 – shayma 2014-11-03 13:50:54

+0

爲什麼要保存文件,然後在保存的文件上獲取InputStream,何時可以直接在url上獲取InputStream?例如,我使用Apache Commons中的HttpMethod.getResponseBodyAsStream()從URL獲取InputStream。當然你有一些相同的方式?或者我誤解了你想要做的事情?顯示更多的代碼可能是一個好主意。 – mwarren 2014-11-03 15:00:40