Tomcat Multipart 请求处理,大文件上传为什么需要先写入到临时文件
RT.
最新在设计一个支持文件传输的RPC协议,底层实现用的NIO,于是就想参考一下Tomcat和Jetty的文件上传实现
不看不知道,一看吓一跳,Tomcat和Jetty都是有个临时文件目录,请求体里的文件大小如果超过了规定的阈值,那么就会先转存到tomcat/jetty的临时文件目录里,然后把这个临时文件的读取流交给之后servlet
两者的逻辑都是先把文件读取完整之后再调用servlet::doPost处理。
而采用临时文件的原因在于这两者都是想一次性读取完所有的输入流之后再交由servlet处理
为什么一定要把文件先读取完之后再处理呢?完全可以封装一个特殊的InputStream,里面的read方法如果没有数据来的时候就会被阻塞住,通过这种方式,把异步转为同步,不需要先做临时文件持久化,我觉得没问题
临时文件这东西如果是在ssd上还凑活,普通hdd开销实在太大
求大佬解惑
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
虽然问题过了一年……不过既然看到了还是来解答下,说说我的看法:
如果 Web Server 不进行文件的“暂存”(内存+磁盘),那如果此时应用程序接收到请求后,它完全可以只读取表单数据而不读取文件,或者在一段时间后再读取文件。
那么在接受到请求 到 读取文件这段时间内,文件流要保持可读取的状态,此时文件不可能全部存储在内存里,所以只能内存存一小部分,剩下的存在磁盘中。
像你说的这种“随写随读”的方式,虽然可行,但结合我上面所说的场景,如果用户没有及时的进行读取文件部分的 Stream,那么对于 Server 端来说,文件很大,TCP 的 RECV_BUF 会很快被读满,从而导致不能再接受新的 TCP 分组,此时整个 TCP 链路可以说是“阻塞的”,因为服务端无法接受新的分组,客户端就不能再发送新的分组。
为什么非
form-data
(multipart) 的请求可以“随存随取”呢?因为报文小,普通的文本报文不会过大,而随便上传一个文件最小都是几百K那如果在 HTTP2 中,由于是“多路复用”的,一个 Host 只用一个 TCP 连接,如果不及时的读取数据,就会造成这个 TCP 连接“阻塞”,导致其他请求的报文也无法传输。
所以为了保证 Server 端可以顺利的读取文件流,TCP连接不受影响,还是需要“暂存”一下的。
你好 这个问题有答案流吗 最近也碰到了