多宽带叠加的分布式云盘:文件秒传、断点续传、大文件下载
*
– 1. 前言
– 2. 各种私有云盘对比
– 3.本云盘实现的功能
– 4. 界面
– 4. 安装
–
+ 4.1 负载均衡服务器
+ 4.1 储存节点
– 5. 代码说明
1. 前言
家中有三条宽带,想通过搭建私有云盘,叠加上传和下载的速度。对比了多种私有云的系统,没找到满足的要求的,所以便萌生出搭建一个可宽带叠加的分布式私有云存储。
2. 各种私有云盘对比
可道云、Nextcloud、易有云:没有多节点。
Cloidreve:有从服务器,但只是用来离线下载的
Seafile:支持ceph分布式储存,只能单节点。
IPFS:去中心化,p2p,未来之星。网关被污染了,有点费硬盘。
Minio: 分布式储存,但传输时只有一个节点传输,别的节点负责加油。
Resilio Sync、微力备份(接近要求,但属于备份软件,比较占储存空间)
jigdo(实现不了,没找到部署教程)(大佬可是试试这个)
3.本云盘实现的功能
√ 多节点
√ 部署简单
√ 文件秒传
√ 断点续传
√ MD5值校验
√ minio存储(防止文件上传漏洞)
√ 大文件下载(数据流的方式,内存占用小)
√ 下载和上传的速度基本取决于宽带上传的下载的速度。
; 4. 界面
上传界面
文件浏览
4. 安装
4.1 负载均衡服务器
负责提供浏览界面,接收客户端的请求,返回文件的md5。
只需修改config.php
$nodes = ['http://ip1:80',"http://ip2:80"];
$dbh = new PDO('mysql:host=localhost;dbname=dbname', "dbuser", "password");
?>
4.1 储存节点
修改
minioClient = Minio('ip:9000',
access_key='minio_key',
secret_key='minio_secret',
secure=False)
buckets = "mydisk"
运行
//运行minio
/home/minio/app/minio server /home/minio/data --config-dir /home/minio/config --console-address :42606 --address :9000
//运行node.py
python3 node.py
5. 代码说明
计算文件的MD5 ,获取切片
function md5(file, chunkSize = 1024*1024*1) {
return new Promise((resolve, reject) => {
let blobSlice = File.prototype.slice || File.prototype.mozSlice || File.prototype.webkitSlice;
let chunks = Math.ceil(file.size / chunkSize);
let currentChunk = 0;
let spark = new SparkMD5.ArrayBuffer();
let fileReader = new FileReader();
var slices = [];
fileReader.onload = function(e) {
spark.append(e.target.result);
currentChunk++;
num = 100*currentChunk/chunks;
num = num.toFixed(2);
jindutiao(num,"计算哈希","#7A0BE2")
if (currentChunk < chunks) {
loadNext();
} else {
slices.push(spark.end());
resolve(slices);
}
};
function loadNext() {
let start = currentChunk * chunkSize;
let end = start + chunkSize;
if (end > file.size){
end = file.size;
}
slice = blobSlice.call(file, start, end);
slices.push(slice);
fileReader.readAsArrayBuffer(slice);
}
loadNext();
});
}
上传片段
function sendChunk(id, chunks,offset,name){
var task=offset.length;
var alllen = chunks.length ;
chunks.forEach(function(chunk, index){
if (offset.length > 0) {text = "断点续传";}
if (offset.length === 0){text = "文件上传";}
if (offset.indexOf(index.toString()) >= 0) {
return;
}
var formData = new FormData();
formData.append('fileId', id);
formData.append('myFileChunk', chunk);
formData.append('chunkIndex', index);
url = nodes[index%nodes.length]+"/success";
console.log(url);
$.ajax({
type: "POST",
url: url,
data: formData,
contentType: false,
processData: false,
async: true,
success: function(done){
console.log("a00" + done + "a00");
if(done == 200){
task =task + 1;
num = 100*task/alllen ;
num = num.toFixed(2);
console.log(index + "已完成" + num.toString() + "%");
jindutiao(num,text)
}
}
})
})
}
进度条
function jindutiao(ini,text,color="pink") {
let texth = document.getElementById("text");
let cont = document.getElementById("cont");
let container = document.getElementById("container");
cont.style.backgroundColor = color;
container.style.display = 'block';
cont.style.width = ini + "%";
if(ini>=100){
text = text + "成功";
ini = 100.00;
}
texth.innerText = text + ": " + ini + "%";
}
下载文件,二进制的方式。
function getBinaryContent(url , i) {
return new Promise((resolve, reject) => {
try {
let xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
resolve({
index: i,
buffer: xhr.response,
});
};
xhr.onprogress=function(event){
if(event.lengthComputable) {
var percentComplete = event.loaded / event.total*100;
percentComplete = percentComplete.toFixed(2);
}
}
xhr.send();
} catch (err) {
reject(new Error(err));
}
});
}
多进程
async function download( urls, poolLimit = 2 ) {
const fileStream= streamSaver.createWriteStream(filename);
const writer = fileStream.getWriter();
const all_part_num = Object.keys(urls).length;
const pools = oneArrToTwoArr([...new Array(all_part_num).keys()],poolLimit*2);
const MD5 = new SparkMD5();
for (let pool of pools) {
var results = await asyncPool(
poolLimit,
pool,
(i) => {
ini = (i+1)/all_part_num*100;
ini = ini.toFixed(2)
jindutiao(ini,"文件下载")
return getBinaryContent(urls[i], i);
}
);
var sortedBuffers = results.map((item) => new Uint8Array(item.buffer));
for (let array of sortedBuffers) {
writer.write(array)
}
}
writer.close();
}
async function asyncPool(poolLimit, array, iteratorFn) {
const ret = [];
const executing = [];
for (const item of array) {
const p = Promise.resolve().then(() => iteratorFn(item, array));
ret.push(p);
if (poolLimit array.length) {
const e = p.then(() => executing.splice(executing.indexOf(e), 1));
executing.push(e);
if (executing.length >= poolLimit) {
await Promise.race(executing);
}
}
}
return Promise.all(ret);
}
下载文件,二进制的方式。
function getBinaryContent(url , i) {
return new Promise((resolve, reject) => {
try {
let xhr = new XMLHttpRequest();
xhr.open("GET", url, true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
resolve({
index: i,
buffer: xhr.response,
});
};
xhr.onprogress=function(event){
if(event.lengthComputable) {
var percentComplete = event.loaded / event.total*100;
percentComplete = percentComplete.toFixed(2);
}
}
xhr.send();
} catch (err) {
reject(new Error(err));
}
});
}
Original: https://blog.csdn.net/liuyuncc/article/details/126142290
Author: 流云cc
Title: 多宽带叠加的分布式云盘:文件秒传、断点续传、大文件下载
原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/748556/
转载文章受原作者版权保护。转载请注明原作者出处!