2014-11-03 79 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