论坛首页 Java企业应用论坛

文件上传:服务器如何终止客户端继续上传

浏览 9528 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2011-04-27  

该场景为:当上传文件不满足要求(服务器端检查:如文件超过大小限制,扩展名不正确等),服务器在等待文件上传完成之前立即返回,目的是终止浏览器继续上传。

 

但是在实际应用中,并不能按上述预想的场景实现,实际情况是:服务器在文件上传过程中关闭响应输出流立即返回,并不能终止浏览器上传,上传的连接依然被保持,浏览器表现为依然在上传文件。

 

Google后,有一篇帖子或多或少说明了这个问题:http://stackoverflow.com/questions/3107631/how-to-close-a-http-connection-from-the-httpservlet

 

写道
ASK:

I'm running a servlet in Tomcat 6.0.26. The servlet accepts file upload from the client by HTTP POST. I'd like to stop the file uploading from the HttpServlet side. I tried the following methods with no luck:

1. close the request inputstream
2. send error code HttpServletResponse.SC_REQUEST_ENTITY_TOO_LARGE and flush response
3. do 1 and 2 in a Filter

I googled but found no direct answers. Please advise solutions.

Thanks.


Answer:

This is not possible using the standard Servlet nor Commons FileUpload API's. Basically, to be able to abort the connection immediately, you should grab the underlying socket physically and close it. However, this socket is controlled by the webserver. See also this related question:How to explicitly terminate http connection from server with no response header.

Little tests have however confirmed that Commons FileUpload doesn't buffer up the entire file in memory when its size exceeds the limit. It will read the input stream, but just ignore and throw away the read bytes (also the ones which are already read). So memory efficiency isn't necessarily the problem here.

To fix the real problem, you'd basically like to validate the file size in the client side rather than the server side. This is possible with a Java Applet or a Flash Application. For example, respectivelyJumpLoaderandSWFUpload.
 

 

测试过程发现,如果上传巨大的文件,服务端(commons-fileupload 实现)会抛出 FileUploadBase$SizeLimitExceededException ,并且服务端立即返回响应;但是浏览器显示仍在上传中(普通html file控件),如果放任其不管,会发现客户端内存不断攀升(并非浏览器进程),服务端内存也不断攀升,直至浏览器失去响应。(因此并非上述帖子中提到 的:如果大小超限,服务端在抛出异常后,会将读取的数据丢弃,因为实际看来这些资源并没有被立即释放)。

 

再次询问有没有好的解决的办法?

   发表时间:2011-04-28  
用nginx限制一下body长度吧、
0 请登录后投票
   发表时间:2011-04-28   最后修改:2011-04-28
弄一个表单, 设置一个文件域, 上传目标为http://www.163.com, 上传一个大文件, 还真会传输的.这可能是http服务器问题吧
0 请登录后投票
   发表时间:2011-04-29  
期待处理过的朋友说下成功的解决方案, 我以前也碰到过, 但不得其果
0 请登录后投票
   发表时间:2011-04-29  
这和http协议有关。

问题的根本在于:在客户端发起http请求完毕之前,压根就没法让客户端终止上传。因为对于这次交互来说,所有的上传数据都属于一个请求之内。

两种做法:
1: 关闭socket连接
2: 获取上传内容后就直接丢掉
0 请登录后投票
   发表时间:2011-04-29  
目前来看 只有楼上的解决办法比较靠谱了。。
0 请登录后投票
   发表时间:2011-04-30  
http 里就是一次输,上传就是上传二进制,你可以参考一下ftp协议,不过这些牵扯的东西太底层了,理论上你用这些神马组件,都是在http上封装了一层,没戏!!!!!!!!!!
0 请登录后投票
   发表时间:2011-04-30  
其实,只要服务器端想中断时,能直接 close 当前http请求底层的socket连接即可,这个浏览器是立即响应的,问题是,servlet/jsp 好像没有提供此类能访问底层的socket连接的api

我曾经也为此苦恼很久,最后的解决办法是,自己用 C++ 写了个简单的 http 服务器,专门做文件上传/下载,没有任何其他功能。
0 请登录后投票
   发表时间:2011-10-11  
解决了,阅读jetty源码,把request强制转换为JETTY的Request解决。
((Request)httpServletRequest).getConnection().getEndPoint().close();
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics