express实现单图,多图,ajax上传图片到oss

版权声明:转载请注明出处并附上原文链接,谢谢! https://blog.csdn.net/CODING_1/article/details/84325468

这段时间没啥事,自己研究了一下express上传图片的操作,这样就摆脱了后台语言使用java的局限,也能对上传的整体流程有更深的理解.当然在继续往下看的前提是大家对express要有简单的认识.最快的方法是看MDN中的图书管理DEMO,这个网址打开需要靠人品:有时候架"梯子"也不好使.

在开始码代码之前我们得先开通阿里云并且需要OSS对象存储,准备好这些我们就开始吧.

前端上传页面,我使用的是art-template模板,当然也可以使用pug,html或其他模板.

views/avatar.art

<form action="./upload_mult" method="post" enctype="multipart/form-data">
  <input type="file" name="avatar" id="avatar" multiple />
  <button class="btn" id="btn" type="submit">提交</button>
</form>

先看一下使用表单提交的方式上传单张图片,这里需要注意一点form中的属性设置,特别是不要忘记指定enctype="multipart/form-data" 接着我们写服务器代码,下面的代码用作与OSS进行交互的配置

controllers/uploadController.js

let co = require('co'); // 这里[co](https://www.npmjs.com/package/co)处理nodejs阻塞问题
let fs = require('fs');
let OSS = require('ali-oss');
let uuidv4 = require('uuid/v4');
let client = new OSS({
  region: '<Your region>',
  accessKeyId: '<Your AccessKeyId>', //OSS控制台,鼠标移到头像时获取
  accessKeySecret: '<Your AccessKeySecret>'
});
var ali_oss = {
  bucket: 'self-upload'
}

分离的routes/catalog.js

//图片上传引用的npm包
var multer  = require('multer'); // 查文档
var upload = multer({ dest: 'upload/' });

// 单图上传 
router.post('/upload', upload.single('avatar'), upload_controller.upload_post);
//多图上传 
router.post('/upload_mult', upload.array('avatar', 3), upload_controller.upload_post);
//混合上传 (不同字段限制数量不同)
var cpUpload = upload.fields([{ name: 'avatar', maxCount: 1 }, { name: 'gallery', maxCount: 3 }])
router.post('/cool-profile', cpUpload, upload_controller.upload_post)

上传的时候首先将图片上传到我们的服务器,然后重命名再传至OSS,最后将我们服务器中的图片删除

controllers/uploadController.js

exports.upload_post = function(req, res, next) {
  if(req.file) {
    // 文件路径
    var filePath = './' + req.file.path; 
    // 文件类型
    var temp = req.file.originalname.split('.');
    var fileType = temp[temp.length - 1];
    var lastName = '.' + fileType;
    // 构建图片名
    var fileName = Date.now() + lastName;
    // 图片重命名
        fs.rename(filePath, fileName, (err) => {
        if (err) {
            res.end(JSON.stringify({status:'102',msg:'文件写入失败'}));   
        }else{
            var localFile = './' + fileName;  
            var key = fileName;
            // 阿里云 上传文件 
            co(function* () {
              client.useBucket(ali_oss.bucket);
              var result = yield client.put(key, localFile);
              var imageSrc = 'http://image.hgdqdev.cn/' + result.name;
              // 上传之后删除本地文件
              res.end(JSON.stringify({status:'100',msg:'上传成功',imageUrl:imageSrc})); 
            }).catch(function (err) {
              // 上传之后删除本地文件
              res.end(JSON.stringify({status:'101',msg:'上传失败',error:JSON.stringify(err)})); 
            });
            fs.unlinkSync(localFile);
        }
    });
  }
  res.end();
}

上面的方法使用与传单张图片,如果是多张图片需要遍历一下,对每一张图片处理,这里将重命名和上传方法进行了拆分并封装到一个对象中

function HandleFile(fileItem) {
  this.fileItem = fileItem;
  this.fileName = '';
  this.localFile = '';
}

/**
 * res: 响应(必填)
 */
HandleFile.prototype.ossUpload = function(res) {
  var self = this;
  co(function* () {
    client.useBucket(ali_oss.bucket);
    var result = yield client.put(self.fileName, self.localFile);
    var imageSrc = result.url;

    res.end(JSON.stringify({ code: 12000, msg:'上传成功', imageUrl:imageSrc }));
  }).catch(function (err) {
    res.end(JSON.stringify({ code:13000,msg:'上传失败', error: err })); 
  });

  self.localFile && fs.unlinkSync(self.localFile);
}

/**
 * res: 响应(必填)
 * next: 错误处理(必填)
 * 给图片重命名后上传
 */
HandleFile.prototype.imgRename = function(res, next) {
  var self = this;

  var filePath = './' + this.fileItem.path;
  var _temp = this.fileItem.originalname.split('.');
  var _fileType = _temp[_temp.length - 1];
  var _lastName = '.' + _fileType;
  this.fileName = uuidv4() + _lastName;
  this.localFile = './' + this.fileName;

  fs.rename(filePath, self.fileName, (err) => {
    if(err) {
      res.end(JSON.stringify({code:13000,msg:'文件上传失败!'}));
    }
    self.ossUpload(res);
  })
}

exports.upload_post = function(req, res, next) {
  if(req.file) {
    new HandleFile(req.file).imgRename(res, next);
  } else if(req.files) {
    var files = req.files;
    files.forEach(function(item) {
      new HandleFile(item).imgRename(res, next);
    })
  }
  res.end(); //为了防止上传出错页面始终处于加载状态,可以自定义处理方法
}

因为单张和多张上传req中的参数是不一样的,单张是req.file, 多张是req.files,代码中需要加一个if判断,如果是ajax再加一个判断:
前端代码修改:

<form>
  <input type="file" name="avatar" id="avatar" />
  <input type="hidden" id="base64" >
  <button class="btn" id="btn" type="button">提交</button>
</form>
<script>
  $('#avatar').change(function() {
    var files = this.files;
    var reader = new FileReader();
    reader.onload = function(event) {
      // console.log(event.target.result);
      $('#base64').val(event.target.result);
    }
    reader.readAsDataURL(files[0]);
  })

  $('#btn').click(function() {
    $.ajax({
      url: 'upload_mult',
      type: 'POST',
      data: { avatar: $('#base64').val() },
      success: function(res) {
        console.log(res);
      },
      error: function(err) {
        console.log(err);
      }
    })
  })
</script>

服务端代码添加:

else if(req.body && req.body.avatar) { // ajax方式提交base64
    var avatar = req.body.avatar;
    var fileName = uuidv4() + '.png';
    var filePath = './upload/' + fileName;
    var base64Data = avatar.replace(/^data:image\/\w+;base64,/, "");
    var dataBuffer = new Buffer(base64Data, 'base64');
    
    fs.writeFile(filePath, dataBuffer, function(err) {
      if(err) {
        res.end(JSON.stringify({code:13000,msg:'文件上传失败!'}));
      } else {
        var handle = new HandleFile();
        handle.fileName = fileName;
        handle.localFile = filePath;
        handle.ossUpload(res);
      }
    })
  }

文章参考 https://blog.csdn.net/zhuming3834/article/details/77531127?locationNum=6&fps=1
DEMO地址: https://github.com/baobz/node-shop

猜你喜欢

转载自blog.csdn.net/CODING_1/article/details/84325468
今日推荐