断点续传问题

我的需求简单描述为:

 对于大文件按照一定的chunkSize大小切分为许多小文件上传存储在mongodb中,
 下载时通过node.js发起n(n为切分的小文件的个数)个下载请求,每个请求请求
 一部分数据,最后通过writeStream写入到同一个文件中。系统的整体流程描述如上。

现在要做的工作是:

 上述的功能已经完成,现在要做的是下载过程中的断点续传问题,即就是下载时如何
 本地文件中已有该部分数据则跳过该部分的下载。

遇到的问题:

现在的问题是,如何用简单的方法判断文件中的某一个部分是否已经存在(我想简单的
通过判断某一块的第一个<0>和最后一个<chunkSize-1>处的文件描述符是否有内容来
判断此块是否已经下载完成),请问各位码友Node.js中的文件描述符fd是否已有像C语言
中的seek方法(文件描述符移动到指定的位置),移动到指定位置后怎么判断此处是否有内容。
谢谢各位码友。
下载部分的代码如下(其中downloadpromise是我自己封装的用来下载每一块数据的Promise):
 function download(filedata,username,chunkSize) {
 var chunks_n = Math.ceil(filedata.length/filedata.chunkSize);
 var file_id = filedata._id;
 var DLpromiseall = [];

 //创建对应的文件,为以后createWrite而使用
 fs.open(filedata.filename, "a", (err, fs) => {
     if (err) {
         console.log(err);
     }
 })
 
 for(let curindex = 0;curindex < chunks_n;curindex++) {
     DLpromiseall.push(downloadpromise(username,file_id,curindex,filedata.filename,chunkSize));
 }
 var mytimer = setInterval(() => {
     if(DLpromiseall.length == chunks_n) {
         clearInterval(mytimer);
         Promise.all(DLpromiseall).then(vales=>{
             console.log(vales);
             console.log("all download")
         }).catch(err =>{
             console.log(err);
             console.log("下载失败");
         })
     }
 },500)
}

downloadPromise函数如下:

 * 文件下载逻辑
 **/
function  downloadpromise(username,file_id,n,filename,chunkSize) {
    return new Promise(function (resolve,reject) {
        let mydata = {
            username: username,
            file_id: file_id,
            n: n
        };
        let contents = queryString.stringify(mydata);
        let options = {
            host: "localhost",
            path: "/nodedownload/",
            port: 8000,
            method: 'POST',
            headers: {
                'Content-Type': 'application/x-www-form-urlencoded',
                'Content-Length': contents.length
            }
        };
        let req = http.request(options, function (res) {
            let bufs = [];
            res.on("data", function (chunk) {
                bufs.push(chunk)
            });
            res.on("end", function (d) {
                console.log("end")
                var resubuf = Buffer.concat(bufs)
                var resu = new Buffer(JSON.parse(resubuf));
                try {
                    let WSoptions = {
                        start: n*chunkSize,
                        flags: "r+"
                    }
                    let WStream = fs.createWriteStream(filename,WSoptions)
                    WStream.write(resu,function () {
                        console.log("This is : "+n);
                    });
                    WStream.end();
                    resolve(filename);
                }catch (err) {
                    console.log(err);
                    reject(err);
                }
            });
            res.on("error", function (e) {
                throw e;
            })
        });
        req.write(contents);
        req.end();
    })
}
阅读 2.2k
2 个回答
上述的功能已经完成,现在要做的是下载过程中的断点续传问题,即就是下载时如何
本地文件中已有该部分数据则跳过该部分的下载。

在原有的http协议,客户端会通过Range请求服务器要返回的部分内容(先判断本地已经下载了几个字节),服务端通过Content-Range告知客户端目前返回下来的部分内容。而你这里多出来的一部只是分块而已,都是一样的。

通过option.start指定文件流开始的位置。

fs.createReadStream(filePath, {
     start: startRange,
     end : endRange //如果需要
});

暂时想到了一个不是很成熟的想法,通过判断每一块里面是否有写入的内容,以及写入的内容是否达到规定写入的标准。代码如下

function readPromise(filepath,i,options) {
    return new Promise(function (resolve,reject) {
        let flag = false;
        let readStream = fs.createReadStream(filepath,options);
        readStream.on("data",(chunk)=>{
            let chunString = chunk.toString().trim();
            let nsize = options.end - options.start + 1;
            if(!chunString||chunString.length < nsize) {
                flag = true;
            }
        })
        readStream.on("close",(ele) => {
            resolve(flag);
        })
        readStream.on("error",(e) => {
            reject(e);
        })
    })
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题