为了账号安全,请及时绑定邮箱和手机立即绑定

在Java Servlet中流式传输大文件

在Java Servlet中流式传输大文件

慕少森 2019-12-11 15:09:41
我正在构建需要扩展的Java服务器。Servlet之一将提供存储在Amazon S3中的图像。最近在负载下,我的VM内存不足,这是在我添加了用于提供图像的代码之后,因此,我很确定流较大的servlet响应会引起我的麻烦。我的问题是:从数据库或其他云存储读取数据时,如何编写Java Servlet以便将大型(> 200k)响应流回浏览器,是否有最佳实践?我考虑过将文件写入本地临时驱动器,然后生成另一个线程来处理流,以便可以重新使用tomcat servlet线程。这似乎很沉重。任何想法将不胜感激。谢谢。
查看完整描述

3 回答

?
慕标5832272

TA贡献1966条经验 获得超4个赞

如果可能,您不应将要提供的文件的全部内容存储在内存中。取而代之的是,为数据获取InputStream,并将数据分段地复制到Servlet OutputStream。例如:


ServletOutputStream out = response.getOutputStream();

InputStream in = [ code to get source input stream ];

String mimeType = [ code to get mimetype of data to be served ];

byte[] bytes = new byte[FILEBUFFERSIZE];

int bytesRead;


response.setContentType(mimeType);


while ((bytesRead = in.read(bytes)) != -1) {

    out.write(bytes, 0, bytesRead);

}


// do the following in a finally block:

in.close();

out.close();

我确实同意toby,您应该改为“将它们指向S3 url”。


至于OOM异常,您确定它与提供图像数据有关吗?假设您的JVM具有256MB的“额外”内存,可用于提供图像数据。在Google的帮助下,“ 256MB / 200KB” =1310。对于2GB的“额外”内存(目前这是一个非常合理的数量),可以支持10,000个并发客户端。即便如此,1300个并发客户端仍然是一个很大的数目。这是您经历过的负载类型吗?如果不是,则可能需要在其他地方查找OOM异常的原因。


编辑-关于:


在这种情况下,图像可能包含敏感数据...


几周前阅读S3文档时,我注意到您可以生成可以附加到S3 URL的过期密钥。因此,您不必公开S3上的文件。我对这项技术的理解是:


初始HTML页面具有指向您的Web应用程序的下载链接

用户点击下载链接

您的Web应用程序会生成一个S3 URL,其中包含一个密钥,该密钥将在5分钟内过期。

使用步骤3中的URL将HTTP重定向发送到客户端。

用户从S3下载文件。即使下载时间超过5分钟,此方法仍然有效-下载开始后,它就可以继续完成。



查看完整回答
反对 回复 2019-12-12
?
ibeautiful

TA贡献1993条经验 获得超5个赞

您为什么不只将它们指向S3网址?从S3中获取工件,然后通过您自己的服务器将其流式传输给我,这使使用S3的目的无法实现,后者是将带宽和将图像提供给Amazon的处理工作卸载了。


查看完整回答
反对 回复 2019-12-12
  • 3 回答
  • 0 关注
  • 446 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信