前端
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="file" id="file">
</body>
</html>
<script>
document.getElementById('file').addEventListener('change', async (e) => {
const file = e.target.files[0];
// 获取文件名
const file_name = file.name.split('.')[0]
let cur = 0;
let size = 1024 * 1024;
const fileChunks = [];
while (cur < file.size) {
fileChunks.push({
file: file.slice(cur, cur + size)
})
cur += size;
}
// 转成请求数组 里面每个都是formData
const requestList = fileChunks
.map(({ file }, index) => {
const formData = new FormData();
formData.append('chunk', file);
// 根据名称加下标格式发送 图片-1
formData.append('file_name', `${file_name}-${index}`)
return { formData }
})
.map(async ({ formData }) => request({
url: "http://localhost:3000",
data: formData
})
)
// 并发发送
await Promise.all(requestList)
// console.log(requestList);
await mergeRequest()
})
// 封装请求
function request({
url,
method = "POST",
data,
header = {},
requestList, // 上传文件列表
}) {
return new Promise(resolve => {
const xhr = new XMLHttpRequest(); // ajax对象
// 请求
xhr.open(method, url)
// 设置请求头
Object.keys(header).forEach(key => {
xhr.setRequestHeader(key, header[key])
});
// 发送数据
xhr.send(data)
xhr.onload = e => {
resolve({
data: e.target.response
})
}
})
}
// 上传成功 合并切片
const mergeRequest = async () => {
await request({
url: "http://localhost:3000/merge",
header: {
"content-type": "application/json"
}
})
alert('ok')
}
</script>
后端
const http = require('http');
const path = require('path');
// 处理表单
const multiparty = require('multiparty')
const server = http.createServer();
const fse = require('fs-extra')
// 要存放切片的地址
const UPLOAD_URL = path.resolve(__dirname, 'target');
server.on('request', async (req, res) => {
res.setHeader('Access-Control-Allow-Origin', "*")
res.setHeader('Access-Control-Allow-Method', "*")
// res.end('ok')
if (req.url === '/') {
// 获取文件/名称;
// 获取POST传过来的表单数据
const multipart = new multiparty.Form();
multipart.parse(req, async (err, fields, files) => {
if (err) {
return;
}
// 获取文件块
const [chunk] = files.chunk;
// 获取文件名称
const [filename] = fields.file_name;
// 切片后的名称
const dir_name = filename.split('-')[0];
// 文件名称地址
const chunkDir = path.resolve(UPLOAD_URL, dir_name)
// 如果这个地址不存在 就创建一个吧
if(!fse.existsSync(chunkDir)){
await fse.mkdirs(chunkDir)
}
// 切片后的文件放到指定文件中夹
await fse.move(chunk.path,`${chunkDir}/${filename}`)
console.log(chunkDir,filename);
})
}else if(req.url === '/merge'){
// 把server/app.js里面合并的代码拿过来就可以
res.end('合并成功')
}
})
server.listen(3000, () => console.log('http://localhost:3000'))