涉及知识点:
ajax请求 (使用:axios)
跨域
post提交
socket交互(使用:socket.io)
buffer接收文件
stream保存文件
前端代码
var socket = io.connect('http://localhost:8080/product')
socket.on('progress', function (p) {
console.log(p + '%')
})
// 获取的文件数据
var file = document.getElementById('file').files[0]
var instance = axios.create({
// 要使用post提交必须设Content-Type为
// application/x-www-form-urlencoded (键值对形式提交)或
// multipart/form-data (二进制形式提交)
headers: { 'Content-Type': 'multipart/form-data' }
})
instance.post('http://localhost:8080/product/upload/img?name=' + file.name + '&size=' + file.size, file)
后端代码
const querystring = require('querystring')
const app = require('http').createServer(handler)
const io = require('socket.io')(app)
// 创建socket链接,这里使用了of进行域限定
const pro = io.of('/product').on('connection', socket => {
// ...
})
function handler (req, res) {
const params = querystring.parse(req.url.split('?')[1])
// 跨域,因前端文件是直接拖到浏览器上运行以file://形式访问,与后台不在同一域,所以要跨域处理
res.writeHead(200, {
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET,POST'
})
// 处理以/product/upload/img开头的请求
if (/^\/product\/upload\/img/.test(req.url)) {
const size = params.size
const name = params.name
const buf = []
let count = 0
// 接收数据事件,会多次触发,chunk的格式为nodejs的Butter,大小不大于65535
req.on('data', (chunk) => {
buf.push(chunk)
count += chunk.length
// 将进度返回给前端
pro.emit('progress', Math.round(count / size * 100))
})
// 数据接收结束保存图片
req.on('end', () => {
// 创建流(stream)
const ws = fs.createWriteStream(path.resolve(__dirname, 'images', name))
// 将暂存好的Buffer写入流
buf.forEach(i => {
ws.write(i)
})
ws.end()
})
}
res.end('{msg:"success"}', 'utf8')
}
app.listen(process.argv[2] || 8080)