以下是一个简单的示例代码,演示了如何使用Node.js的Koa2框架结合Vue3实现文件的分片上传:
在服务器端(Node.js + Koa2):
```javascript
const Koa = require('koa');
const Router = require('koa-router');
const bodyParser = require('koa-bodyparser');
const fs = require('fs');
const app = new Koa();
const router = new Router();
// 设置中间件
app.use(bodyParser());
// 处理文件分片上传
router.post('/upload', async (ctx) => {
const { filename, index, total, data } = ctx.request.body;
const uploadPath = `./uploads/${filename}`;
const writeStream = fs.createWriteStream(uploadPath, { flags: 'a' });
// 将分片数据追加写入文件
writeStream.write(Buffer.from(data, 'base64'));
// 如果是最后一个分片,则关闭写入流,表示上传完成
if (index === total - 1) {
writeStream.end();
ctx.body = {
message: 'Upload complete',
file: uploadPath,
};
} else {
ctx.body = {
message: 'Upload in progress',
};
}
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(3000, () => {
console.log('Server is running on http://localhost:3000');
});
在客户端(Vue3):
<template>
<div>
<input type="file" @change="handleFileChange" />
<button @click="startUpload">Start Upload</button>
<p>{{ message }}</p>
<p>{{ progress }}</p>
</div>
</template>
<script>
export default {
data() {
return {
file: null,
message: '',
progress: 0,
};
},
methods: {
handleFileChange(event) {
this.file = event.target.files[0];
},
async startUpload() {
const CHUNK_SIZE = 1024 * 1024; // 分片大小
const totalChunks = Math.ceil(this.file.size / CHUNK_SIZE);
let currentChunk = 0;
while (currentChunk < totalChunks) {
const start = currentChunk * CHUNK_SIZE;
const end = Math.min(this.file.size, start + CHUNK_SIZE);
const chunk = this.file.slice(start, end);
const chunkReader = new FileReader();
chunkReader.readAsDataURL(chunk);
await new Promise((resolve) => {
chunkReader.onload = async (event) => {
const data = event.target.result;
const response = await fetch('http://localhost:3000/upload', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
filename: this.file.name,
index: currentChunk,
total: totalChunks,
data: data.split(',')[1], // 去除base64前缀
}),
});
const result = await response.json();
if (result.message === 'Upload in progress') {
this.message = 'Uploading...';
this.progress = Math.round(((currentChunk + 1) / totalChunks) * 100);
currentChunk++;
resolve();
} else if (result.message === 'Upload complete') {
this.message = 'Upload complete';
this.progress = 100;
resolve();
}
};
});
}
},
},
};
</script>