Skip to content

Commit

Permalink
feat: 大文件分片上传-封装 fetch 添加进度
Browse files Browse the repository at this point in the history
  • Loading branch information
songxingguo committed Jun 11, 2024
1 parent 60dc057 commit df29d6d
Show file tree
Hide file tree
Showing 2 changed files with 42 additions and 66 deletions.
60 changes: 10 additions & 50 deletions src/.vuepress/public/demo/FileUpload/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,60 +19,20 @@ const resolvePost = (req) =>
});
});

const pipeStream = (path, writeStream) =>
new Promise((resolve) => {
const readStream = fse.createReadStream(path);
readStream.on("end", () => {
fse.unlinkSync(path); // 移除
resolve();
});
readStream.pipe(writeStream);
});

const mergeFileChunk = async (filePath, fileHash, size = 5 * 1024 * 1024) => {
// console.log(filePath, filename, size)
// 大文件上传时,设计后端思想时每个要上传的文件,先以文件名,
// 为target目录名,把分文件blob,放入这个目录
// 文件blob上传前要加上index
// node 文件合并肯定可以的,stream
const chunkDir = path.resolve(UPLOAD_DIR, fileHash);
// console.log(chunkDir);
// 合并切片
const mergeFileChunk = async (filePath, fileHash) => {
const chunkDir = `${UPLOAD_DIR}/${fileHash}`;
const chunkPaths = await fse.readdir(chunkDir);
// console.log(chunkPaths); // 路径下的数组文件名
// 根据切片下标进行排序,否则直接读取目录的获得的顺序可能会错乱
chunkPaths.sort((a, b) => a.split("-")[1] - b.split("-")[1]);
// console.log(chunkPaths, '++');
// 每块内容写入最后的文件,promise
await Promise.all(
chunkPaths.map((chunkPath, index) =>
pipeStream(
// 回流的方法
path.resolve(chunkDir, chunkPath),
fse.createWriteStream(filePath, {
start: index * size,
end: (index + 1) * size,
})
)
)
);
console.log("文件合并成功");
fse.rmdirSync(chunkDir); // 删除
await fse.writeFile(filePath, "");
chunkPaths.forEach((chunkPath) => {
fse.appendFileSync(filePath, fse.readFileSync(`${chunkDir}/${chunkPath}`));
fse.unlinkSync(`${chunkDir}/${chunkPath}`);
});
fse.rmdirSync(chunkDir); // 合并后删除保存切片的目录
};

// 合并切片
// const mergeFileChunk = async (filePath, fileHash) => {
// const chunkDir = `${UPLOAD_DIR}/${fileHash}`;
// const chunkPaths = await fse.readdir(chunkDir);
// // 根据切片下标进行排序,否则直接读取目录的获得的顺序可能会错乱
// chunkPaths.sort((a, b) => a.split("-")[1] - b.split("-")[1]);
// await fse.writeFile(filePath, "");
// chunkPaths.forEach((chunkPath) => {
// console.log("chunkPath", chunkPath);
// fse.appendFileSync(filePath, fse.readFileSync(`${chunkDir}/${chunkPath}`));
// fse.unlinkSync(`${chunkDir}/${chunkPath}`);
// });
// fse.rmdirSync(chunkDir); // 合并后删除保存切片的目录
// };

// 返回已经上传切片名列表
const createUploadedList = async (fileHash) =>
fse.existsSync(`${UPLOAD_DIR}/${fileHash}`)
Expand Down
48 changes: 32 additions & 16 deletions src/.vuepress/public/demo/FileUpload/大文件分片上传.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,43 @@
* @param {Object} FetchConfig fetch config
* @return {Promise} fetch result
*/
const requestApi = ({ url, method = "GET", ...fetchProps }) => {
const requestApi = ({
url,
method = "GET",
onProgress,
...fetchProps
}) => {
const controller = new AbortController();
abortControllerList.push(controller);
return (
fetch(url, {
return new Promise(async (resolve, reject) => {
const res = await fetch(url, {
method,
...fetchProps,
signal: controller.signal,
})
//返回请求成功的结果
.then((res) => res && res.status === 200 && res.json())
// .catch((err) => alert("未知错误", err))
.then((res) => {
// 将请求成功的 xhr 从列表中删除
const aCIndex = abortControllerList.findIndex(
(c) => c.signal === controller.signal
);
abortControllerList.splice(aCIndex, 1);
return res;
})
);
});
const total = res.headers.get("content-length");
const reader = res.body.getReader(); //创建可读流
const decoder = new TextDecoder();
let loaded = 0;
let data = "";
while (true) {
const { done, value } = await reader.read();
loaded += value?.length || 0;
data += decoder.decode(value);
const progress = (loaded / total) * 100;
console.log("上传进度:", progress);
onProgress && onProgress(progress);
if (done) {
break;
}
}
// 将请求成功的 xhr 从列表中删除
const aCIndex = abortControllerList.findIndex(
(c) => c.signal === controller.signal
);
abortControllerList.splice(aCIndex, 1);
resolve(JSON.parse(data));
});
};

// 文件分片
Expand Down

0 comments on commit df29d6d

Please sign in to comment.