2

前言

本人不是技术专家,该笔记只是从使用语言进行开发的层面上记录一些体会,不包含也不想尝试从源码或者更深的层次去讨论语言本身的优劣。文章内容是笔者的个人感悟,既不保证正确性,也不保证别人能看懂。

这竟然是该笔记的第二篇,虽然不确定以后会不会有第三篇。

第一篇在这里:NodeJS学习笔记: require, exports 和 module.exports 的初印象

引子

事实上我是基于MEANJS框架开始NodeJS的探索的,相对于angularJS而言,服务器端的坑真实太多了,虽然npm上很多模块可以使用,但是大部分没有详细的文档,真是毁人不倦啊。
在MEANJS的demo演示中提供了用户头像的功能,本次学习目的是把文件上传功能独立出来。前端的上传处理使用的是angular-file-upload

正文

我的目标是提供一个上传文件的表单,数据库端将会存放如下的数据:

  1. 文件id

  2. 用户id

  3. URL

  4. MIME-TYPE

  5. 文件大小

  6. 原始文件名

  7. 标题,如果是图片这个通常用来说明图片的主题,这里我设置为必填了。

  8. 描述,如果是图片这个放在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不靠谱,文档太简单,搜索无答案的时候还是看源码靠谱。所以,同学们的源码要保持格式,同时易读哦。


incNick
6.3k 声望554 粉丝

普通的PHP开发工程师