前言
本人不是技术专家,该笔记只是从使用语言进行开发的层面上记录一些体会,不包含也不想尝试从源码或者更深的层次去讨论语言本身的优劣。文章内容是笔者的个人感悟,既不保证正确性,也不保证别人能看懂。
这竟然是该笔记的第二篇,虽然不确定以后会不会有第三篇。
引子
事实上我是基于MEANJS框架开始NodeJS的探索的,相对于angularJS而言,服务器端的坑真实太多了,虽然npm上很多模块可以使用,但是大部分没有详细的文档,真是毁人不倦啊。
在MEANJS的demo演示中提供了用户头像的功能,本次学习目的是把文件上传功能独立出来。前端的上传处理使用的是angular-file-upload。
正文
我的目标是提供一个上传文件的表单,数据库端将会存放如下的数据:
文件id
用户id
URL
MIME-TYPE
文件大小
原始文件名
标题,如果是图片这个通常用来说明图片的主题,这里我设置为必填了。
描述,如果是图片这个放在alt中比较好,可选。
好吧,开始。
前端第一坑:formData
angular-file-uploader提供了formData,但是我尝试了很久这个数据也传送不到我的PHP服务器上。没错,这里我用了PHP,这个我比较熟。
窍门:很多同学喜欢写完了功能再调试,这其实非常麻烦,
因为中间的任何一步错了都导致结果不对,
我通常对于没有实足把握的步骤都是立即测试的。
解决方案:在其实例的onBeforeUploadItem事件被触发的时候再写入formData,而且要用push防止覆盖原始数据。
uploader.onBeforeUploadItem = function(fileItem) {
fileItem.formData.push({
title: $scope.upload.title
});
};
前端的一个小细节
如果没有选择要上传的文件,其实例uploader的方法uploadAll()是无法被成功调用的,所以
if (uploader.queue.length) {
uploader.uploadAll();
} else {
//用普通的REST方式提交,仅限于update
}
multer的使用
终于到正文了。官方支持的文档在这里,超简单。
var multerConfig = {
dest: './modules/uploads/client/uploads/', // Normal file upload destination path
limits: {
fileSize: 10*1024*1024 // Max file size in bytes (10 MB)
},
fileFilter: function (req, file, cb) {
var mimetypes = (['text/*', 'image/*', 'video/*', 'audio/*', 'application/zip']).join(',');
var testItems = file.mimetype.split('/');
if ((new RegExp('\\b' + testItems[0] + '/\\*', 'i')).test(mimetypes) || (new RegExp('\\*/' + testItems[1] + '\\b', 'i')).test(mimetypes) || (new RegExp('\\b' + testItems[0] + '/' + testItems[1] + '\\b', 'i')).test(mimetypes)) {
cb(null, true);
} else {
return cb(new Error('Only image, plain text, audio, video and zip format files are allowed!'), false);
}
} // fileFilter要在这里声明才行,用instance.fileFilter = funciton(){};是不管用的
};
var upload = multer(multerConfig).single('userUploadFiles');//single是指前端angular-file-uploader指定的用来保存文件内容的字段
//除了single还有fields, array方法,是用来处理多文件上传的,官方文档有,用法大同小异。
//下面是关键了,我一直都取不到自定义的title和description字段,req.body, req.query, req.params都是空的,req.file和req.files是undefined,为什么呢?
upload(req, res, function (uploadError) {
//**在这个时候,req.file才出现**(如果不是用的single方法,那么此时req.files出现),同时title和description也被添加到req.body中
//好了,后面不用说了,你们懂
if (uploadError) {
//错误处理
} else {
//正常处理,就是删掉被覆盖的文件稍微麻烦点,但也不是问题。
}
});
总结
Demo不靠谱,文档太简单,搜索无答案的时候还是看源码靠谱。所以,同学们的源码要保持格式,同时易读哦。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。