月份:2018年1月
密码保护:《王者接龙》游戏设计案
不撞南墙心不死,一个multiparty花了二天时间没搞定
其实没什么,只是在小程序里做一个上传图片的功能。
前端用微信自己提供的上传控件。
后端用nodejs+express+multiparty
一开始的时候,我看网上说用connect-multipart,刚准备试一下,才发现这玩意已不被express推荐。
然后又看到有人说直接用bodyparse就可以了,结果发现新版本的bodyparse根本不支持multipart/form,不能用于上传文件。
然后就用了multiparty。
真是大坑啊。
由于我现在用了router,所以建立server的时候是在router前面就已经建了。
所以到了最终操作multiparty的时候,我只要New一个form就好了。
然后用form.parse来解析,发现没用,收不到文件。
于是跑去用multer,这个东西是express在文档里直接支持的,但是试了一下没效果。
这时翻回来用multiparty,在winscp刷新了一下,发现原来已经收到了N个文件,之前测试的时候留的,当时看不到,是因为winscp不刷新的话,即使打开一百次文件夹都看不到新文件。
这时才知道这玩意可以用。
大喜过望,但是可惜的是,form.parse里的callback没用,只有在一种情况下它起作用,那就是当创建form的时候路径写错了,就可以在callback里打印err.message。除此之外,是绝对没用的。
如果直接在form.parse后面写res.send来向前端返回数据,那么等于都不知道有没有上传成功就贸然回复。
后来看到有人说在express2和3里,bodyparse还能管着multipart/form类型,所以一定要把json和encode两种类型单独写,不要直接写一个app.use(bodyparse)。
但是我本来就没有这么写,所以这个答案对我没意义。
而且我用nmp list express查了一下,当前版本是4.x,在这个版本中bodyparse已经被阉割了。
不过我一直怀疑这个答案是最接近真相的,于是我把bodyparse给注释了,测试结果是:没用。
然后用bing查英文资料,有个老外说他遇到的问题是80k以上的文件就会无法进行form.parse,他的解决方案是用busboy,我不想就这么放弃,所以没采纳。
还有个老外也说有这个问题,但最后他自己说他是在两个地方多次require(multiparty)导致的,而且他建议我们不要用app.use,但我没这些毛病啊。
最后,终于找到一篇博客,这老外说express4下要用multiparty,但官方文档太简单了,没有卵用,所以他自己写了一个示例。
然后我照着他的示例终于拿到了fields。
因为他用到了一个我完全没想到的事件,form.on(‘field’,function(name,value){})
当然,他的写法事实上官方文档里也不是没有。
这种写法的思路是将autoFile设为false,从而能够得到part事件、close事件,自己处理文件流。
然而经测,part事件和close都没有触发。
结果就是,我可以拿到表单内容,也可以拿到文件,但是永远也无法知道文件的名称。因为文件名称是multiparty自己生成的临时名称。
其实办法不是没有,大不了我每次弄个临时文件来放文件,转移文件之后把文件夹给删了,每次一个文件,就不怕找不到文件夹,而且我还准备了一个更坑爹的做法,就是发两次请求,第一次把json发过来,用json中的名称建好文件夹等着它,然后第二个请求就对号入座。
但是真的不甘心啊,这也太麻烦了吧。
另外令我无语的是,form.on(‘field’,callback)会多次触发,有几个表单项就触发几次,而且我们可以想像的是,fields是收到请求立刻就被解析出来的,而文件什么时候收完,什么时候存储完成,这都是multiparty自己在后面黑着做的,既然form.parse自带的callback无效,那我还有什么办法呢?写一个定时器一直刷文件夹??
这个中间件明明是一个使用人数超多的产品,为什么我遇到这么大一个问题却找不到答案呢?
如果说我的代码写得有问题,那么应该收不到文件,或者拿不到field,但问题是两者都可以做到,真是要被它搞疯了。
如果按我的习惯,我是不会为这么一个中间件花这么多时间的,但是现在就是花了这么多时间,真是太扯了。
最后,我把官方文档又仔细看了一遍,终于把问题搞定了,Part事件就是当原始的请求来了一截之后就触发,当有一个field来了,它就会触发,有一个文件来了,它也会触发。
不过可惜的是,文件上传并不是一个连续的过程,而是分块的,而且好像微信默认就是分块的,结果而我现在的写法只能收到第一块,这一点可以从form.on(‘progress’,(bytesReceived, bytesExpected)=>{})得知,收是收了很多次,但是最后写成的文件只有第一次收的大小。
所以现在的问题就是怎么把20K以上的文件收完整。
现在收不完,close事件就永远也不会被触发。
不行只好读一下multiparty源码,看看它到底怎么回事。
nodejs接收post数据返回404的原因
真的是蠢爆了。
一般用原生的node或express写个单页面,是通过app.get/app.post/app.all来对get和post方法进行处理的。
用了路由,就是router.get和router.all/post什么的。
但我一开始并没有注意这router.get中的get其实是get方法,我一直以为get是只是router组件自带的一个什么配置方法。
所以复制的代码一直用的get。
后来把router.get改成router.all,立刻不再出现404了。
醉啊醉。
node.js cannot find module ‘mongodb’
话说,想在项目里用mongodb,结果node报错。
上网一查,光安装了mongo本身是不行的。
还得用npm安装一下相关的东东
操作如下(第二步是项目根目录)
npm install mongodb -g cd /path/to/my/app/folder npm link mongodb