2012-03-13 70 views
0

总之,我有一个Servlet,它检索图片/视频e t.c.来自底层数据存储。为ServletResponce指定InputStream,而不是在OutputStream中复制InputStream

为了归档此我需要将文件的InputStream复制到ServletResponce * 的OutputStream *

从我的角度来看,这不是有效的,因为我需要复制的文件内存发送之前,指定InputStream会更方便,在读取缓冲区中的数据后,OutputStream会读取数据并立即发送。

我看着ServletResponce文档,它有一些缓冲区的消息数据,所以我有几个关于它的问题。

这是正确的机制吗? 如果我决定在Servlet处理结束时不发送文件? 例如: 如果我抄的InputStream的OutputStream,然后发现,这不是授权请求,用户无权查看该对象(错误在设计也许)我仍然会发送一些数据客户,尽管这不是我想要的,或者不是。

回答

0

这是正确的机制吗?

基本上,它是由Servlet APIs提供的机构。考虑到这一点,您需要设计您的servlet。

(这是很难看到它可能做任何其他方式。一个read系统调用从设备(磁盘)读取数据到内存中。一个write系统调用从内存到一个设备中写入数据(网络接口)。没有系统调用可以直接将数据从一个设备传输到另一个设备,最好的办法是减少应用程序中的数据复制量如果您使用类似IOUtils.copy的东西,可以避免通过应用程序memort的唯一方法是使用针对内容传输优化的一些专用硬件/操作系统组合。)

但是,这可能是无论如何。在大多数情况下,性能瓶颈可能是数据在网络上的移动。数据可能会从磁盘读取到内存,复制并写入网络接口的速度要比通过网络传输到用户的Web浏览器(或其他)快几个数量级。

如果它不是没有争议,那么一个实际的内容交付方式是使用一个单独的web服务器在本地代码中实现,我们优化以提供静态内容;例如类似nginx。)

如果我决定不在Servlet处理结束时发送文件?例如:如果我已将InputStream复制到OutputStream中,然后发现这不是授权请求,并且用户无权查看此对象(可能是设计错误),但我仍然会向客户端发送一些数据,虽然这是不是我想要的,或者不是。

你应该编写你的servlet来进行访问检查,然后再将内容读入内存。理想情况下,在通过发送响应头“提交”响应之前。

1

为了解决您的第一关注,你可以轻松地复制到InputStream使用OutputStreamIOUtils阿帕奇百科全书郎咸平:

IOUtils.copy(fileInputStream, servletOutputStream); 

它采用4K缓冲,所以内存的消耗不应该是一个问题。事实上,你不能直接发送来自InputStream的数据。在最低级别,操作系统仍然需要将文件内容读取到某个内存位置,并且为了将其发送到套接字,您需要提供要发送数据的内存位置。流只是一个有用的抽象。

关于第二个问题:这就是HTTP的工作原理:如果您开始将数据流传输到客户端,那么servlet容器会首先发送所有响应标头。如果在中间中止,从客户端角度看,它看起来像中断的下载。

+0

我正好利用IOUtils.copy为我处理已经:) 最关心的是第二个问题 - 这是从我的角度来看,流动,因为我不想送任何东西,直到Servlet的处理已经结束,这可能容易出错。 4K缓冲区是IOUtils缓冲区的默认大小,因此使用另一个用于Servlet处理的缓冲区将不会有效。 如果我想发送8K数据报,我要么需要使用IOUtils读取两次,要么添加可配置的复制实现。 – mavarazy 2012-03-13 14:04:03

相关问题