vue+node.js实现扫码

实现理念

2000毫秒截取一张摄像头当前录到数据转换base64给服务器发过去 服务器通过解码base64后保存文件到本地之后使用qrcode-reader校验是否为二维码 之后删除文件 给前端相应码中数据 或 提示这不是一个码

使用npm包一览

"jimp": "^0.16.1"
"multer": "^1.4.2"
"qrcode-reader": "^1.0.4"
"body-parser": "^1.19.0"
"express": "^4.17.1"

生成二维码得地址

[草料](https://cli.im/)

布局

<template>
    <div class = 'qr-send'>
        <video id="video" width="100%" height="100%"></video>
        <div class = 'line-wrap'>
            <div class = 'line' v-if = 'showLine'></div>
        </div>
        <canvas width="100%" height="100%" id = 'canvas'></canvas>
        <img id = 'images' width = '100%' height = '100%'/>
    </div>
</template>

样式

<style>
    .line {
        width: 80%;
        height: 1px;
        margin: 0 auto;
        box-shadow: 0 2px 3px #0ff,
                    0 5px 3px #0ff,
                    0 5px 3px #0ff,
                    0 5px 3px #0ff,
                    0 5px 3px #0ff,
                    0 8px 3px #0ff;
    }

    .line-wrap {
        width: 100%;
        position: absolute;
        left: 0;
        top: 200px;
        animation:myfirst 5s infinite;
        transition: 2s linear;
    }

    @keyframes myfirst
    {
        from {
            top: 200px;
        }
        to {
            top: 1200px;
        }
    }
</style>

打开摄像头

在项目生命周期mounted时启动摄像头
获取屏幕宽高得目的是为canvas和img标签设置宽高达到全屏显示

		// 获取屏幕宽高
        let height = window.screen.availHeight;
        const width = window.screen.availWidth;
        const canvas = document.getElementById("canvas");
        const images = document.getElementById("images");
        // height += 300;
        canvas.width = width;
        canvas.height = height;
        let constraints = {
            video: {width, height},
            audio: true
        };
        const tis = this;
        
        navigator.mediaDevices.getUserMedia(constraints)
        .then(function(mediaStream) {
            var video = document.querySelector('video');
            video.srcObject = mediaStream;
            video.onloadedmetadata = function(e) {
                video.play();
                tis.showLine = true;
            };
        }).catch(function(err) { console.log(err.name + ": " + err.message); });

        const timer = setInterval (() => {
            this.takePhoto(width, height, timer);
        }, 2000);

截取图片并上传

// 保存图片到canvas
            takePhoto(w, h, timer) {
                //获得Canvas对象
                let canvas = document.getElementById("canvas");
                let ctx = canvas.getContext('2d');
                ctx.drawImage(video, 0, 0, w, h);
                const base64 = canvas.toDataURL("image/png");  
                // 上传base64
                qr_decode({
                    base64
                }).then (res => {
                    if (res.code === '0000') {
                        clearInterval(timer);
                        console.log(res);
                    }
                });
            }

后端

1.基础配置

var express = require('express');
var bodyParser = require('body-parser');
const decodeImage = require('jimp').read;
const qrcodeReader = require('qrcode-reader');
var app = express();
const { writeFile, readFile, unlink } = require('fs');

app.use(bodyParser.json({limit: '1mb'}));
app.use(bodyParser.urlencoded({
  extended: true
}));

var urlencodedParser = bodyParser.urlencoded({ extended: false });

app.all('*', function(req, res, next) {
  res.setHeader('Access-Control-Allow-Headers', '*');
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', '*');
  next();
});
const config = {
	port: 8808
};
	const { port } = config;

var server = app.listen(port, function () {
 
  var host = server.address().address
  var port = server.address().port
 
  console.log('\033[42;30m DONE \033[40;32m server open success port::' + port)

});

2.路由

app.post('/file', urlencodedParser, async function (req, res) {
  const base64 = req.body.base64.replace(/^data:image\/\w+;base64,/, "");
  const path = './update/'+ Date.now() +'.png';
  var dataBuffer = Buffer.from(base64, 'base64');
  await writeFile(path, dataBuffer, function(err) {
      if(err){
          console.log(err);
      } else {
        qr_decode(path, res);
      }
  });
});

3.解码

function qr_decode (pathName, res) {
  readFile(pathName, function(errorWhenReadUploadFile, fileBuffer) {
    decodeImage(fileBuffer, function(errorWhenDecodeImage, image) {
      let decodeQR = new qrcodeReader();
      decodeQR.callback = function(errorWhenDecodeQR, result) {
        if (result === undefined) {
          removeFile(pathName, res);
        } else {
          res.send(JSON.stringify({
            code: '0000',
            msg: '解码成功',
            data: result.result
          }));
          console.log(result);
        }
      };
      decodeQR.decode(image.bitmap);
    });
  });
}

4.删除文件

function removeFile (pathName, res) {
  unlink(pathName, (err) => {
    if(err) throw err;
    res.send(JSON.stringify({
      data: null,
      code: "9990",
      msg: '不是二维码(没有找到二维码信息)'
    }));
  });
}
  • 4
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值