feat(transfer): download everything to tmp dir to prevent unfinish transfers

This commit is contained in:
Alexey Kasyanchuk
2018-09-02 08:17:44 +03:00
parent 7098bdd0b3
commit 4334463e3c
2 changed files with 47 additions and 12 deletions

View File

@ -0,0 +1,15 @@
const fs = require('fs')
module.exports = function deleteFolderRecursive(path) {
if (fs.existsSync(path)) {
fs.readdirSync(path).forEach(function(file, index){
var curPath = path + "/" + file;
if (fs.lstatSync(curPath).isDirectory()) { // recurse
deleteFolderRecursive(curPath);
} else { // delete file
fs.unlinkSync(curPath);
}
});
fs.rmdirSync(path);
}
};

View File

@ -12,6 +12,7 @@ const ph = require('path')
const directoryFilesRecursive = require('./directoryFilesRecursive')
const {promisify} = require('util');
const mkdirp = promisify(require('mkdirp'))
const deleteFolderRecursive = require('./deleteFolderRecursive')
class p2p {
constructor(send = () => {})
@ -413,7 +414,7 @@ class p2p {
return () => callbacks.forEach(callback => callback())
}
file(path, targetPath, remotePeer)
file(path, targetPath, remotePeer, parent)
{
if(!this.dataDirectory)
{
@ -430,16 +431,19 @@ class p2p {
logT('transfer', 'get file request', path)
const promise = new Promise(async (resolve) =>
{
const filePath = this.dataDirectory + '/' + (targetPath || path)
// recreate directory to file if not exist
await mkdirp(ph.dirname(filePath))
const realPath = (targetPath || path).replace(/\\/g, '/')
const filePath = this.dataDirectory + '/' + realPath
const tmpPath = this.dataDirectory + '/' + realPath.split('/').map(p => p + '.tmp').join('/')
// create temporary directory and file for downloading
await mkdirp(ph.dirname(tmpPath))
let fileStream
if(!fs.existsSync(filePath) || !fs.lstatSync(filePath).isDirectory())
fileStream = fs.createWriteStream(filePath)
if(!fs.existsSync(tmpPath) || !fs.lstatSync(tmpPath).isDirectory())
fileStream = fs.createWriteStream(tmpPath)
let peer = null
let firstTransfer = false
let deleteCallback = (remotePeer || this).emit('file', {path}, (chunk, nil, addr) => {
let deleteCallback = (remotePeer || this).emit('file', {path}, async (chunk, nil, addr) => {
if(peer && addr !== peer)
{
logT('transfer', 'ignore other peers responce', addr.peerId)
@ -454,8 +458,20 @@ class p2p {
fileStream.end()
if(firstTransfer) // данные передало до этого, значит файл целый
{
const renameCallback = async () => {
await mkdirp(ph.dirname(filePath))
fs.renameSync(tmpPath, filePath)
}
if(parent)
{
resolve(renameCallback)
}
else
{
await renameCallback()
resolve(true)
}
}
return
}
@ -466,14 +482,18 @@ class p2p {
logT('transfer', 'get folder content', filesList)
deleteCallback()
const transferFiles = () => {
Promise.all(filesList.map(file => this.file(file, null, addr))).then(() => {
Promise.all(filesList.map(file => this.file(file, null, addr, true))).then(async (files) => {
// files transfers, now move it from tmp dir
Promise.all(files.map((renameCallback) => renameCallback())).then(() => {
deleteFolderRecursive(tmpPath)
logT('transfer', 'finish transfer all files from folder')
resolve()
})
})
}
if(fileStream)
fileStream.end(null, null, () => {
fs.unlinkSync(filePath)
fs.unlinkSync(tmpPath)
transferFiles()
})
else