需求
客户端无法拍摄实物并上传
解决方案
1.客户端生成二维码 为二维码提供页面地址 并建立WebSocket连接
2.手机扫码二维码 并建立WebSocket连接 上传图片到服务器
3.服务端转发图片地址到客户端
Vue
- qrcode -- 生成二维码
- axios -- 上传formData
- vue-router -- 路由
Client.vue
<template>
<div>
<canvas id="canvas"></canvas>
<img :src="img" alt="" style="width:200px" />
</div>
</template>
<script>
import QRCode from "qrcode";
const ws = new WebSocket("ws://192.168.1.8:8000");
export default {
data() {
return {
img: "",
};
},
mounted() {
this.getQR();
ws.addEventListener("open", this.handlerOpen.bind(this), false);
ws.addEventListener("close", this.handlerClose.bind(this), false);
ws.addEventListener("error", this.handlerError.bind(this), false);
ws.addEventListener("message", this.handlerMessage.bind(this), false);
},
methods: {
getQR() {
QRCode.toCanvas(
document.getElementById("canvas"),
"http://192.168.1.8:8080/#/mobile",
function(error) {
if (error) console.error(error);
console.log("success!");
}
);
},
handlerOpen(e) {
console.log("Open");
},
handlerClose(e) {
console.log("Close");
},
handlerError(e) {
console.log("Error");
},
handlerMessage(e) {
this.img = e.data;
},
},
};
</script>
Mobile.vue
<template>
<div>
<input type="file" id="upload" accept="image/jpg" @change="upload" />
<img :src="img" id="show" width="200" />
</div>
</template>
<script>
const ws = new WebSocket("ws://192.168.1.8:8000");
export default {
data() {
return {
uploadUrl: "http://192.168.1.8:7001/api/img",
img: "",
};
},
mounted() {
ws.addEventListener("open", this.handlerOpen.bind(this), false);
ws.addEventListener("close", this.handlerClose.bind(this), false);
ws.addEventListener("error", this.handlerError.bind(this), false);
ws.addEventListener("message", this.handlerMessage.bind(this), false);
},
methods: {
upload(e) {
const formData = new FormData();
formData.append("file", e.target.files[0]);
this.uploadImg(formData);
},
uploadImg(formData) {
this.$axios({
url: this.uploadUrl,
method: "post",
data: formData,
processData: false,
contentType: false,
}).then((res) => {
this.img = res.data.url;
this.handlerSendMsg(res.data.url);
});
},
handlerSendMsg(imgUrl) {
ws.send(imgUrl);
},
handlerOpen(e) {
console.log("Open");
},
handlerClose(e) {
console.log("Close");
},
handlerError(e) {
console.log("Error");
},
},
};
</script>
node
- multer -- 处理图片
- ws -- WebSocket
- express -- 服务
index.js
const Ws = require("ws");
const express = require("express");
const app = express();
const cors = require("cors");
const bodyParser = require("body-parser");
app.use("/uploads", express.static(__dirname + "/uploads"));
app.use(bodyParser());
app.use(cors());
require("./routes/upload.js")(app);
app.listen(7001, () => {
console.log("http://localhost:7001");
});
const server = new Ws.Server({
port: 8000,
});
const init = () => {
bindEvent();
};
function bindEvent() {
server.on("open", handleOpen);
server.on("close", handleClose);
server.on("error", handleError);
server.on("connection", handleConnection);
}
function handleOpen(e) {
console.log("open");
}
function handleClose(e) {
console.log("close");
}
function handleError(e) {
console.log("error");
}
function handleConnection(ws) {
console.log("connection");
ws.on("message", handleMsg);
}
function handleMsg(msg) {
server.clients.forEach(c => {
c.send(msg)
});
}
init();
upload.js
module.exports = (app) => {
const express = require("express");
const router = express.Router();
const multer = require("multer");
var storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "uploads/");
},
filename: function (req, file, cb) {
cb(null, file.originalname);
},
});
var upload = multer({ storage: storage });
router.post("/img", upload.single("file"), async (req, res) => {
const file = req.file;
file.url = `http://192.168.1.8:7001/uploads/${file.filename}`;
res.send(file);
});
app.use("/api", router);
};