node实现图片上传功能

方式一

以流的形式上传图片直接返回路径,这样写:
好处:方便处理存取数据返回路径
不好的地方:可能冗余,上传的文件后面并未使用

1.用koa-body中间件

注:如果已经使用了koa-bodyParser中间件,请remove此中间件,koa-body可以代替koa-bodyParser

在app.js中使用该中间件
const koaBody = require('koa-body')
app.use(koaBody({
  multipart: true
}));
注:由于图片上传文本类型为:multipart/form-data,所以需加上此条件

2.前端代码调用

注:我用的vue+antd vue写的前端,其余框架同理

3.后端node实现

(1).在/controllers/upload.js中写入
var upload_img = async (ctx, next) => {
  // 上传单个文件
  console.log(ctx.request.files.uploadImg, '==========================')
  const file = ctx.request.files.uploadImg // 获取上传文件
  // 创建可读流
  const reader = fs.createReadStream(file.path);
  let name=stringRandom(16, { numbers: true })+'.png';
  let filePath = path.join(__dirname, '../public/upload/') + name;
  // 创建可写流
  const upStream = fs.createWriteStream(filePath);
  // 可读流通过管道写入可写流
  reader.pipe(upStream);
  return ctx.body = {
    code:200, 
    data:{
      path:`/upload/${name}`,
      name:file.name
    },
    message:"上传成功!"
  } ;
};
(2)在app.js中写入:
const path = require('path');
const static = require('koa-static');//配置静态资源
//设置静态资源路径
app.use(static(
  path.join(__dirname, 'public'),{    //静态文件所在目录
      maxage: 30*24*60*60*1000        //指定静态资源在浏览器中的缓存时间
  }
));
注:(1)ctx.request.files.uploadImg,由于前端的upload组件name为uploadImg,所以这里写uploadImg
(2)写入静态资源读取,便于前端访问该图片
(3)该方法的本质:获取图片上传者图片在他电脑位置,把这张图片通过管道存入我们指定的自己的服务器上

方式二

为了不造成服务器图片冗余,减少无需图片上传,实现:
1.前端每次上传生成base64图片(可预览)
2.当整个表单提交之后再把这个图片的base64提交给后台
3.后台接受base64图片,通过buffer转为图片格式,用stringRandom生成随机数为图片名字存储到服务器。

1.前端每次上传生成base64图片

前端代码:
<template>
<div>
  <h4>上传base64图片</h4>
  <input type="file" @change="Preview($event)" accept="image/*" ref="showinput">
  <div>图片名字:{{imgName}}</div>
  <img :src="imgData" alt="">
  <a-button  type="primary" @click="handleSubmit">上传</a-button>

</div>
</template>

<script>
import {SubmitBaseImg} from '../assets/js/getData'
export default {
  data (){
    return {
      imgName:'',
      imgData:'',
    };
  },
  methods:{
    Preview(ev){
        // const self=this;
        const file=ev.target.files[0];
        this.imgName=file.name;
        console.log('图片文件',ev.target.files);
        this.imgObj=ev.target.files[0];
        let obj=new FileReader();
        obj.readAsDataURL(file);
        // obj.onload=function(){
        //   self.img=obj.result;
        // }
        obj.onload=()=>{
            this.picReduce(obj.result,base64=>{
                this.imgData=base64
            });
        };
    },
    // 图片压缩
    picReduce(picObj,callback){
        let img = new Image();
        img.src=picObj;
        img.onload=()=>{
            const w=img.width;
            const h=img.height;
            const scale = w/h;
            const max_w=w>1080?1080:w;
            const max_h=h*max_w/w;
            let canvas=document.createElement("canvas");
            let ctx = canvas.getContext('2d');
            canvas.width=max_w;
            canvas.height=max_h;
            ctx.drawImage(img,0,0,max_w,max_h);
            var base64 = canvas.toDataURL('image/jpeg', 0.7);
            callback(base64)
        }
    },
    handleSubmit(){
      SubmitBaseImg({imgData:this.imgData,imgName:this.imgName}).then(msg=>{
        if(msg.code==200){

        }
      })
    },
  },
  mounted(){},
}

</script>
<style lang='less' scoped>
</style>

2.后台接受base64图片,通过buffer转为图片格式,用stringRandom生成随机数为图片名字存储到服务器

const stringRandom = require('string-random');
var upload_baseImg = async (ctx, next) => {
  let  {imgData,imgName}=ctx.request.body;
  //过滤data:URL
  var base64Data = imgData.replace(/^data:image\/\w+;base64,/, "");
  var dataBuffer = Buffer.from(base64Data, 'base64');
  let name=stringRandom(16, { numbers: true })+'.png';
  console.log('图',name);
  // let name='图.png';
  let filePath = path.join(__dirname, '../public/upload/') + `${name}`;
  return new Promise((res,rej)=>{
    fs.writeFile(filePath, dataBuffer, function(err) {
      console.log(111,err);
      if(err){
        res({...errorResObj})
      }else{
        res({
          ...responseObj,
          data:{
            path:`/upload/${name}`,
            name:imgName
          },
        })
      }
    });
  }).then(msg=>{
    ctx.response.body=msg;
  })
  
}

posted @ 2020-07-01 11:38  米牙  阅读(1509)  评论(0编辑  收藏  举报