手机h5 页面扫码上传图片 同步显示到pc端
還是那句老話 一切技術為公司業務服務!?
這不這天產品又來新思路了,小趙啊,我們的客戶不想每次上傳圖片還得跑到電腦上傳,能不能手機掃碼 ,在手機上拍照點擊上傳 就自動顯示到pc上了
?
我說可以啊,用戶掃碼之后跳到一個 h5 頁面 用戶在那個頁面拍照 成功之后 點擊上傳就到我們的系統中了
問題是? 現在后端是用php寫的? ?我當時想到了兩種方式 一個是ajax輪詢 但是吧那個代價好像有點大? ?也比較耗費客戶端的性能 想了想還是算了
第二種就是? 使用websocket ,那樣的話 需要后端搭建一個 websocket 服務器
剩下的就交給前端來處理了
1. 我就菜鳥一個? ?稍微懂點websocket的皮毛而已? 大概就是知道有這個玩意 至于干嘛的? 也不太清除
反正閑著也是沒事 我就用nodejs 搭建一個 玩一玩
?
需求的知識 是 : node.js? ?koa? layui? js基礎? ?ok
先來看下效果吧:? 我用谷歌模擬的:? ? 最左側是圖片信息? ?中間 模擬用戶的掃碼出來的h5 頁面? ?右側是 pc頁面? ?當用戶點擊上傳的時候? ?就會把圖片的上傳成功后的地址推送到pc端然后進行展示
由于 我只是個前端菜鳥 不懂數據庫? ?全程都是數據寫死的? 進行模擬的? ? ? 原諒小菜鳥技術菜哈?
?
2. 代碼邏輯展示?
首先是上傳部分的前端代碼? ? 偷懶了 我用layui? 直接實例化了一個? 上傳組件??
<!DOCTYPE html> <html> <head><title>掃碼上傳</title><link rel="stylesheet" type="text/css" href="https://www.layuicdn.com/layui-v2.5.6/css/layui.css" /><script src="/socket.io/socket.io.js"></script></head><body><div class="layui-upload-drag" id="test10"><i class="layui-icon"></i><p>點擊上傳,或將文件拖拽到此處</p><div class="layui-hide" id="uploadDemoView"><hr><img src="" alt="上傳成功后渲染" style="max-width: 196px"></div></div><script src="https://cdn.bootcdn.net/ajax/libs/layui/2.5.7/layui.min.js"></script><script>// 上面的引入之后 會有一個 io對象let socket = io.connect('/'); // 鏈接到服務器layui.use(['jquery', 'upload', 'layer'], () => {var $ = layui.jquery, upload = layui.upload, layer = layui.layer;//拖拽上傳upload.render({elem: '#test10', url: 'http://192.168.5.16:3000/accept' //改成您自己的上傳接口, done: function (res) {socket.emit('msg', {imgPath: res.imgPath})layer.msg('上傳成功');}});})</script> </body></html>2.1? nodejs? 后端代碼? ?這里我也偷懶了 使用了? koa 框架 快速搭建了
正常來說吧? ?在業務上 其實當你上傳成功之后 應該會返回一個 圖片的存儲地址? ?然后通過socket 發給pc端 端 圖片地址? ? ?
不過 我在koa 這里也寫出了? 圖片的上傳后端代碼
const Koa = require('koa'); const koaBodyParser = require('koa-bodyparser'); const KoaRouter = require('koa-router'); const fs = require('fs'); // 文件讀寫 const koaBody = require('koa-body'); const koaParty = require('koa2-multiparty'); const views = require('koa-views') const IO = require('koa-socket-2'); const io = new IO(); // 注冊socketconst app = new Koa(); io.attach(app); // app 是koa 的實例app.use(views(__dirname + '/views', {extension: 'ejs' })) // 上傳文件 app.use(koaBody({multiparty: true,//支持文件上傳ecoding: 'gzip',formidable: { //對上傳數據進行限制maxFieldsSize: 20 * 1024 * 1024},keepExtensions: true })) app.use(koaBodyParser()) var router = new KoaRouter(); router.post('/accept', koaParty(), async ctx => {let file = ctx.req.files.file;let imgPath = file.path;let name = file.name;const fileReader = fs.createReadStream(imgPath);// 創建一個文件讀取流// 定義文件存儲路徑var fileDir = __dirname + '/public/img'const filePath = `${fileDir}/${name}`; // 真正的項目中圖片名字是隨機生成的,防止重復//創建文件輸出流const fileWrite = fs.createWriteStream(filePath);// 寫入文件數據fileReader.pipe(fileWrite);// ctx.body ="success";ctx.body = {code: 200,msg: '請求成功!',imgPath: 'filePath'}; }) // 監聽鏈接 app._io.on('connection', socket => {// 監聽客戶端的msg 事件socket.on('msg', (data) => {app._io.emit('msg', {...data}); // 模擬 這里直接使用了廣播形式 偷懶了})console.log('connect success!'); }) router.get('/', async ctx => {await ctx.render('index'); }) router.get('/xianshi', async ctx => {await ctx.render('xianshi'); }) app.use(router.routes())// 注冊路由 app.listen(8080, () => {console.log('服務器開啟成功!'); })2.2 展示頁面
socket.on? ?監聽服務器推送來的消息
let socket = io.connect('/'); // 鏈接到服務器socket.on('msg', function(data) {console.log(data)$('img').attr('src', "http://192.168.5.16:3000/img/" + data.imgPath);})這下 就實現了? ? ?上面很多的都是模擬數據? ?要替換成你本地的哈
?
注意 最后我還是發現了一個 很嚴重的問題 我是用過其他的方式規避了 :
就是如果你使用的是 koa的腳手架創建的項目, <script src="/socket.io/socket.io.js"></script>? ?這句話 他會找不到 socket.io.js 文件? 不用靜態文件托管的話? 是正常的? 就比如在瀏覽器中輸入http://localhost:8080/socket.io/socket.io.js? 會顯示 下面的代碼? ??
? ?否則的話, 因為他會認為是在 public文件夾下? ? 這就會打亂socket 原來的文件位置? 導致找不到服務? ?就不會顯示出上面的代碼了? 很奇怪
排查的問題是? ?如果你使用 koa腳手架的 啟動的話 他是通過bin目錄下的 www 進行啟動的??
我們看下那個文件?
他好像? 重新 使用 http.createServer? 生成了一個服務器? 導致 我們得io 一直找到不到 路徑? ? 把這個去掉 倒是可以了? ?很奇怪? 也不知道這個問題官方發現了沒有
#!/usr/bin/env node/*** Module dependencies.*/ var app = require('./app'); var debug = require('debug')('demo:server'); var http = require('http'); /*** Get port from environment and store in Express.*/var port = normalizePort(process.env.PORT || '3000'); // app.set('port', port);/*** Create HTTP server.*/var server = http.createServer(app.callback());/*** Listen on provided port, on all network interfaces.*/server.listen(port); server.on('error', onError); server.on('listening', onListening);/*** Normalize a port into a number, string, or false.*/function normalizePort(val) {var port = parseInt(val, 10);if (isNaN(port)) {// named pipereturn val;}if (port >= 0) {// port numberreturn port;}return false; }/*** Event listener for HTTP server "error" event.*/function onError(error) {if (error.syscall !== 'listen') {throw error;}var bind = typeof port === 'string'? 'Pipe ' + port: 'Port ' + port;// handle specific listen errors with friendly messagesswitch (error.code) {case 'EACCES':console.error(bind + ' requires elevated privileges');process.exit(1);break;case 'EADDRINUSE':console.error(bind + ' is already in use');process.exit(1);break;default:throw error;} }/*** Event listener for HTTP server "listening" event.*/function onListening() {var addr = server.address();var bind = typeof addr === 'string'? 'pipe ' + addr: 'port ' + addr.port;debug('Listening on ' + bind); }到現在也沒找到合適的? 解決方法? 有大神知道的話 請告知??
總結
以上是生活随笔為你收集整理的手机h5 页面扫码上传图片 同步显示到pc端的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: [羊城杯 2020]Easyphp2
- 下一篇: 启动服务器在线教育,国内首个k12在线教