使用SocketIO传图片

更新时间: 2024-11-25 11:25:31

之前实现了文字传输,现在提高一下难度传输图片,大致的思路如下:

  1. 在服务器上放一堆图片
  2. 读取图片列表,在客户端连上的时候将图片列表返回给客户端
  3. 客户端点击某个图片名称,就发送名称给服务端
  4. 服务端用fs模块获取到图片的二进制数据并发送给客户端
  5. 客户端接收到图片然后转码展示

先看一下效果吧

# 传输文件列表

使用fs模块:

const fileList = fs.readdirSync('./img')
1

然后在客户端连上的时候将fileList发出去:

















 






const express = require('express')
const fs = require('fs')
const {createServer} = require('node:http')
const {Server} = require('socket.io')  

const app = express() 
const server = createServer(app)
const io = new Server(server,{
    cors: {
      origin: "*"
    }
})

const fileList = fs.readdirSync('./img')

io.on('connection', (socket) => {
    socket.emit('fileList', fileList)
})

server.listen(3000, () => {
    console.log('server running at http://localhost:3000')
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22

然后客户端监听 fileList 事件,并保存:

const fileList = ref([])

socket = io("http://192.168.2.122:3000")

socket.on('fileList', (list) => {
    fileList.value = list
})
1
2
3
4
5
6
7

# 向服务端发送要请求的图片

将fileList渲染成列表,点击列表项时,向socket发送select事件

<template>
  <div class="main">
    <ul class="img-ul">
      <li v-for="item in fileList" @click="selectImg(item)">{{item}}</li>
    </ul>
  </div>
</template>

<script setup>
  import {ref, onMounted} from "vue"
  import {io} from  "socket.io-client/dist/socket.io.js" 
  let socket = null
  const fileList = ref([])

  onMounted(() => {

    socket = io("http://192.168.2.122:3000")

    socket.on('fileList', (list) => {
      console.log('fileList',list)
      fileList.value = list
    })
  })

  function selectImg(filename) {
    socket.emit('select', filename)
  }
</script>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

# 服务端返回图片数据

服务端监听select事件并读取对应的图片数据:

socket.on('select', (filename) => {
    fs.readFile('./img/'+filename, (err, buf) => {
        socket.emit('image', buf)
    })
})
1
2
3
4
5

# 客户端解析收到的图片二进制数据

socket.on('image', (img, historyList) => {
    const blob = new Blob([img])
    history.value = historyList
    imageSrc.value = URL.createObjectURL(blob)
})
1
2
3
4
5

# 完整代码

# 客户端

<template>
  <div class="main">
    <ul class="img-ul">
      <li v-for="item in fileList" @click="selectImg(item)">{{item}}</li>
    </ul>
    <div class="img-wrapper">
      <div>历史记录:{{history.join(',')}}</div>
      <img class="img" :src="imageSrc" alt="">
    </div>
  </div>
</template>

<script setup>
  import {ref, onMounted} from "vue"
  import {io} from  "socket.io-client/dist/socket.io.js" 
  let socket = null
  const fileList = ref([])
  const history = ref([])
  const imageSrc = ref('')

  onMounted(() => {

    socket = io("http://192.168.2.122:3000")

    socket.on('fileList', (list) => {
      console.log('fileList',list)
      fileList.value = list
    })

    socket.on('image', (img, historyList) => {
      const blob = new Blob([img])
      history.value = historyList
      imageSrc.value = URL.createObjectURL(blob)
    })
  })

  function selectImg(filename) {
    socket.emit('select', filename)
  }
</script>

<style scoped>
.main {
  position: fixed;
  top:0;
  left:0;
  right:0;
  bottom:0;
  display: flex;
}
.img-ul {
  list-style: none;
  padding:0;
  margin:0;
  background-color: brown;
  width: 250px;
  height:100%;
}
.img-ul li {
  padding: 3px 7px;
  cursor: pointer;
  color: rgba(255,255,255,0.6);
}
.img-ul li:hover {
  color: rgba(255,255,255,1);
}
.img-wrapper {
  flex: 1;
}
</style>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70

# 服务端

const express = require('express')
const fs = require('fs')
const {createServer} = require('node:http')
const {Server} = require('socket.io')  

const app = express() 
const server = createServer(app)
const io = new Server(server,{
    cors: {
      origin: "*"
    }
})

const fileList = fs.readdirSync('./img')

io.on('connection', (socket) => { 
    const list = []

    socket.emit('fileList', fileList)

    socket.on('select', (filename) => {
        list.push(filename)
        fs.readFile('./img/'+filename, (err, buf) => {
            socket.emit('image', buf, list)
        })
    })
})

server.listen(3000, () => {
    console.log('server running at http://localhost:3000')
})
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31