node koa2实现上传图片并且同步上传到七牛云存储


Posted in Javascript onJuly 31, 2017

因为升级到新的node版本,之前的通过很多上传图片的方式都已经不适用了,所以自己就写了一个对于 koa2上传图片的小demo,记录一下心得。

废话不多说,下面直接上代码,里面都有注释。

const Koa = require('koa');
const route = require('koa-route');
const serve = require('koa-static');
const inspect = require('util').inspect
const path = require('path')
const os = require('os')
const fs = require('fs')
const Busboy = require('busboy')
const qiniu = require('qiniu')
const qiniuConfig = require('./qiniuconfig')

 
const app = new Koa();

app.use(serve(__dirname + '/public/'));

 
// 写入目录
const mkdirsSync = (dirname) => {
 if (fs.existsSync(dirname)) {
  return true
 } else {
  if (mkdirsSync(path.dirname(dirname))) {
   fs.mkdirSync(dirname)
   return true
  }
 }
 return false
}

function getSuffix (fileName) {
 return fileName.split('.').pop()
}

// 重命名
function Rename (fileName) {
 return Math.random().toString(16).substr(2) + '.' + getSuffix(fileName)
}
// 删除文件
function removeTemImage (path) {
 fs.unlink(path, (err) => {
  if (err) {
   throw err
  }
 })
}
// 上传到七牛
function upToQiniu (filePath, key) {
 const accessKey = qiniuConfig.accessKey // 你的七牛的accessKey
 const secretKey = qiniuConfig.secretKey // 你的七牛的secretKey
 const mac = new qiniu.auth.digest.Mac(accessKey, secretKey)

 const options = {
  scope: qiniuConfig.scope // 你的七牛存储对象
 }
 const putPolicy = new qiniu.rs.PutPolicy(options)
 const uploadToken = putPolicy.uploadToken(mac)

 const config = new qiniu.conf.Config()
 // 空间对应的机房
 config.zone = qiniu.zone.Zone_z2
 const localFile = filePath
 const formUploader = new qiniu.form_up.FormUploader(config)
 const putExtra = new qiniu.form_up.PutExtra()
 // 文件上传
 return new Promise((resolved, reject) => {
  formUploader.putFile(uploadToken, key, localFile, putExtra, function (respErr, respBody, respInfo) {
   if (respErr) {
    reject(respErr)
   }
   if (respInfo.statusCode == 200) {
    resolved(respBody)
   } else {
    resolved(respBody)
   }
  })
 })

}

// 上传到本地服务器
function uploadFile (ctx, options) {
 const _emmiter = new Busboy({headers: ctx.req.headers})
 const fileType = options.fileType
 const filePath = path.join(options.path, fileType)
 const confirm = mkdirsSync(filePath)
 if (!confirm) {
  return
 }
 console.log('start uploading...')
 return new Promise((resolve, reject) => {
  _emmiter.on('file', function (fieldname, file, filename, encoding, mimetype) {
   const fileName = Rename(filename)
   const saveTo = path.join(path.join(filePath, fileName))
   file.pipe(fs.createWriteStream(saveTo))
   file.on('end', function () {
    resolve({
     imgPath: `/${fileType}/${fileName}`,
     imgKey: fileName
    })
   })
  })

  _emmiter.on('finish', function () {
   console.log('finished...')
  })

  _emmiter.on('error', function (err) {
   console.log('err...')
   reject(err)
  })

  ctx.req.pipe(_emmiter)
 })
}



app.use(route.post('/upload', async function(ctx, next) {

  const serverPath = path.join(__dirname, './uploads/')
 // 获取上存图片
 const result = await uploadFile(ctx, {
  fileType: 'album',
  path: serverPath
 })
 const imgPath = path.join(serverPath, result.imgPath)
 // 上传到七牛
 const qiniu = await upToQiniu(imgPath, result.imgKey)
 // 上存到七牛之后 删除原来的缓存图片
 removeTemImage(imgPath)
 ctx.body = {
  imgUrl: `http://xxxxx(你的外链或者解析后七牛的路径)/${qiniu.key}`
 }
}));
 
app.listen(3001);

console.log('listening on port 3001');

然后在同一级目录下,创建一个public文件夹,然后在下面新建一个 index.html,因为我们上面已经把这个文件夹设置为静态访问文件夹了, public/index.html 的代码为

<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <title>Document</title>
</head>
<body>
  <input id="btn1" type="file" name="file"/> 
 <input id="btn2" type="submit" value="提交"/>
</body>
<script>
  
  var btn1 = document.querySelector('#btn1')
  var btn2 = document.querySelector('#btn2')
  var file = null
  btn1.addEventListener('change', function(e){
    file = e.target.files[0]
  })

  btn2.onclick = function(){
  var _data = new FormData();
  _data.append('file', file);
  xhr(_data)
  }

  var xhr = function(formdata){
    var xmlHttp = new XMLHttpRequest(); 

    xmlHttp.open("post","http://127.0.0.1:3001/upload", true); 
     
    xmlHttp.send(formdata);

    xmlHttp.onreadystatechange = function(){ 
     if(xmlHttp.readyState==4){ 
       if(xmlHttp.status==200){ 
         var data = xmlHttp.responseText; 
         console.log(data); 
       } 
     }
    }
  }
</script>
</html>

选择好图片,然后点击提交,就可以上传到你的七牛空间啦!

源代码在 github: https://github.com/naihe138/koa-upload

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Javascript 相关文章推荐
setTimeout 不断吐食CPU的问题分析
Apr 01 Javascript
点击文章内容处弹出页面代码
Oct 01 Javascript
基于Jquery的开发个代阴影的对话框效果代码
Jul 28 Javascript
动态加载外部javascript文件的函数代码分享
Jul 28 Javascript
在标题栏显示新消息提示,很多公司项目中用到这个方法
Nov 04 Javascript
基于jquery实现即时检查格式是否正确的表单
May 06 Javascript
jQuery 翻页组件yunm.pager.js实现div局部刷新的思路
Aug 11 Javascript
微信小程序 增、删、改、查操作实例详解
Jan 13 Javascript
vuejs2.0运用原生js实现简单的拖拽元素功能示例
Feb 24 Javascript
Vue.js 十五分钟入门图文教程
Sep 12 Javascript
浅谈Vue.js中如何实现自定义下拉菜单指令
Jan 06 Javascript
基于layui的table插件进行复选框联动功能的实现方法
Sep 19 Javascript
Angular.js初始化之ng-app的自动绑定与手动绑定详解
Jul 31 #Javascript
详解React中的组件通信问题
Jul 31 #Javascript
Angular.js前台传list数组由后台spring MVC接收数组示例代码
Jul 31 #Javascript
Angular.js中数组操作的方法教程
Jul 31 #Javascript
BootStrap导航栏问题记录
Jul 31 #Javascript
Angular4 中内置指令的基本用法
Jul 31 #Javascript
详谈ES6中的迭代器(Iterator)和生成器(Generator)
Jul 31 #Javascript
You might like
十大催泪虐心动漫电影,有几部你还没看
2020/03/04 日漫
PHP模拟SQL Server的两个日期处理函数
2006/10/09 PHP
PHP学习 运算符与运算符优先级
2008/06/15 PHP
教你如何快捷的使用cmd访问mysql小技巧
2014/05/26 PHP
PHP使用ODBC连接数据库的方法
2015/07/18 PHP
PHP+mysql+ajax轻量级聊天室实现方法详解
2016/10/17 PHP
浅谈PHP中new self()和new static()的区别
2017/08/11 PHP
php-fpm服务启动脚本的方法
2018/04/27 PHP
jquery异步请求实例代码
2011/06/21 Javascript
JS清除IE浏览器缓存的方法
2013/07/26 Javascript
javascript实现textarea中tab键的缩排处理方法
2015/06/26 Javascript
jQuery实现仿QQ在线客服效果的滚动层代码
2015/10/15 Javascript
JS之相等操作符详解
2016/09/13 Javascript
vue.js通过自定义指令实现数据拉取更新的实现方法
2016/10/18 Javascript
JavaScript实现反转字符串的方法详解
2017/04/27 Javascript
Node.js实现发送邮件功能
2017/11/06 Javascript
vue实现裁切图片同时实现放大、缩小、旋转功能
2018/03/02 Javascript
详解react-refetch的使用小例子
2019/02/15 Javascript
vue-resourc发起异步请求的方法
2020/02/11 Javascript
解决vue cli4升级sass-loader(v8)后报错问题
2020/07/30 Javascript
[06:30]DOTA2英雄梦之声_第15期_死亡先知
2014/06/21 DOTA
flask中使用SQLAlchemy进行辅助开发的代码
2013/02/10 Python
实例讲解python函数式编程
2014/06/09 Python
简单介绍Python下自己编写web框架的一些要点
2015/04/29 Python
Python数据结构之翻转链表
2017/02/25 Python
python3利用Dlib19.7实现人脸68个特征点标定
2018/02/26 Python
解决pycharm运行时interpreter为空的问题
2018/10/29 Python
django echarts饼图数据动态加载的实例
2019/08/12 Python
python实现简单的购物程序代码实例
2020/03/03 Python
CSS3提交意见输入框样式代码
2014/10/30 HTML / CSS
美国独家设计师眼镜在线光学商店:Glasses Gallery
2017/12/28 全球购物
什么是接口(Interface)?
2013/02/01 面试题
检察机关个人对照检查材料
2014/09/15 职场文书
泸县召开党的群众路线教育实践活动总结大会新闻稿
2014/10/21 职场文书
毕业生爱心捐书倡议书
2015/04/27 职场文书
Python实战之疫苗研发情况可视化
2021/05/18 Python