我想在post header到达之后, 文件开始上传之前或者刚开始上传时拒绝post请求 目前使用的方式是在加载bodyparse时设置 app.use(express.bodyParser({ limit: 1000000 //1m })); 这样一来浏览器确实收到一个413,而且后台也没有临时文件出现, 但是浏览器依然在上传文件, 我不知道后台有没有在继续处理这个请求, 如果有的话应该也是占用了不少资源和带宽, 如何能彻底的把文件大上传拒绝掉呢?
传统的express上传文件是,post header发生完毕,然后添加到服务器的临时目录后,在根据size()方法判断是否过大,如果过大就返回413。 而在express.bodyParser( { limit: 3242 } ) 设置最大限制也的确发送了header 头之后,当文件过大也不会拷贝到临时目录 你说的这种,应该后台在处理,否则怎么运用limit属性判断文件是否过大呢
@anubiskong 既然都返回413了,那服务器就已经返回了,问题可能是浏览器的socket还在,可以用netstat查看是否那个socket连接还在,另:如果还不放心,用nginx代理,同样可以限制大小,那样如果超过最大设置,请求压根不会到node进程。
首先,看看socket.end()
的解释:
Half-closes the socket. i.e., it sends a FIN packet. It is possible the server will still send some data.
因此socket.end()
不会关闭浏览器的连接,而你应该调用的是socket.destroy()
:
Ensures that no more I/O activity happens on this socket. Only necessary in case of errors (parse error or so).
另外确认你服务器进程两个地方:
- 那个
socket
连接还在的话,状态是否是ESTABLISHED
,如果是WAIT_TIME
或者其它的状态是没有问题的 - 检查相应
fd
是否存在
你自己描述问题也说了:
- 服务器返回了
413
,浏览器收到了413
- 服务器没有保存文件
- 浏览器依然在上传
针对第三点,你判断浏览器依然在上传的标准是什么呢?Pending
么?在chrome调试器里都返回413
了,按道理是不可能出现Pending
状态的。所以你按照我第一次给的代码,直接abort()
是最简单粗暴的办法。
另外,见代码:
- https://github.com/stream-utils/raw-body/blob/master/index.js#L27-L39
- https://github.com/expressjs/body-parser/blob/master/index.js#L43
express的中间件body-parser
只是将socket暂停了(通过调用.pause()
),然后抛出错误,所以你要也可以这么写:
app.use(function onError(err, req, res) {
if (err && err.status === 413)
req.socket.destroy();
})
@yorkie 我测试中发现了很多奇怪的现象 其实浏览器没有立即收到413, 而是在文件上传之后收到的, 这是在上传4g的大文件时发现的, 一开始我用的是100m的文件, 瞬间传完, 所以没有发现. 另外是, 我试着写了一段代码监控data事件, 当data累计长度超过1m的时候取消所有的data事件和end事件监听(req.removeAllListeners), 然后上传一个100m的文件测试, 我发现这个代码在一次上传请求中被执行了7次, 没有搞明白是为什么 还有就是4g的大文件上传, 即便传完了也没有413发到浏览器, 浏览器什么回复也没有收到, 如果看jquery的xhr, 会发现status=404…
@anubiskong
你可以仔细看看raw-body这个lib的实现,express的limit是通过它实现的,它是在如果没有提供length的前提下会在data
事件中计算出当前的received,超过limit后413,取消事件监听是因为raw-body
有cleanup()
. 最好是发出部分代码才比较好分析。
我的邮箱:[email protected]