diff --git a/backend/app.js b/backend/app.js index e508616..732982a 100644 --- a/backend/app.js +++ b/backend/app.js @@ -54,24 +54,109 @@ app.post('/tomp3', function(req, res) { var date = Date.now(); var path = audioPath; var audiopath = Date.now(); - youtubedl.exec(url, ['-o', path + audiopath + ".mp3", '-x', '--audio-format', 'mp3'], {}, function(err, output) { + youtubedl.exec(url, ['-o', path + audiopath + ".mp3", '-x', '--audio-format', 'mp3', '--write-info-json'], {}, function(err, output) { if (err) { audiopath = "-1"; throw err; } }); + + // write file info + + youtubedl.getInfo(url, function(err, info) { + if (err) throw err; + + var size = info.size; + fs.writeFile("data/"+audiopath, size, function(err) { + if(err) { + return console.log(err); + } + + console.log("The file was saved!"); + }); + }); var completeString = "done"; var audiopathEncoded = encodeURIComponent(audiopath); res.send(audiopathEncoded); res.end("yes"); }); +function getFileSizeMp3(name) +{ + var jsonPath = audioPath+name+".mp3.info.json"; + + if (fs.existsSync(jsonPath)) + var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); + else + var obj = 0; + + return obj.filesize; +} + +function getAmountDownloadedMp3(name) +{ + var partPath = audioPath+name+".mp3.part"; + if (fs.existsSync(partPath)) + { + const stats = fs.statSync(partPath); + const fileSizeInBytes = stats.size; + return fileSizeInBytes; + } + else + return 0; +} + +function getFileSizeMp4(name) +{ + var jsonPath = videoPath+name+".info.json"; + var filesize = 0; + if (fs.existsSync(jsonPath)) + { + var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); + var format = obj.format.substring(0,3); + for (i = 0; i < obj.formats.length; i++) + { + if (obj.formats[i].format_id == format) + { + filesize = obj.formats[i].filesize; + } + } + } + + return filesize; +} + +function getAmountDownloadedMp4(name) +{ + var format = getVideoFormatID(name); + var partPath = videoPath+name+".f"+format+".mp4.part"; + if (fs.existsSync(partPath)) + { + const stats = fs.statSync(partPath); + const fileSizeInBytes = stats.size; + return fileSizeInBytes; + } + else + return 0; +} + +function getVideoFormatID(name) +{ + var jsonPath = videoPath+name+".info.json"; + if (fs.existsSync(jsonPath)) + { + var obj = JSON.parse(fs.readFileSync(jsonPath, 'utf8')); + var format = obj.format.substring(0,3); + return format; + } +} + app.post('/tomp4', function(req, res) { var url = req.body.url; var date = Date.now(); var path = videoPath; var videopath = Date.now(); - youtubedl.exec(url, ['-o', path + videopath + ".mp4", '-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4'], {}, function(err, output) { + youtubedl.exec(url, ['-o', path + videopath + ".mp4", '-f', 'bestvideo[ext=mp4]+bestaudio[ext=m4a]/mp4', '--write-info-json'], {}, function(err, output) { if (err) { videopath = "-1"; throw err; @@ -88,14 +173,19 @@ app.post('/mp3fileexists', function(req, res) { var exists = ""; var fullpath = audioPath + name + ".mp3"; if (fs.existsSync(fullpath)) { - exists = basePath + audioPath + name; + exists = [basePath + audioPath + name, getFileSizeMp3(name)]; } else { - exists = "failed"; + var percent = 0; + var size = getFileSizeMp3(name); + var downloaded = getAmountDownloadedMp3(name); + if (size > 0) + percent = downloaded/size; + exists = ["failed", getFileSizeMp3(name), percent]; } //console.log(exists + " " + name); - res.send(JSON.stringify(exists)); + res.send(exists); res.end("yes"); }); @@ -104,14 +194,19 @@ app.post('/mp4fileexists', function(req, res) { var exists = ""; var fullpath = videoPath + name + ".mp4"; if (fs.existsSync(fullpath)) { - exists = basePath + videoPath + name; + exists = [basePath + videoPath + name, getFileSizeMp4(name)]; } else { - exists = "failed"; + var percent = 0; + var size = getFileSizeMp4(name); + var downloaded = getAmountDownloadedMp4(name); + if (size > 0) + percent = downloaded/size; + exists = ["failed", getFileSizeMp4(name), percent]; } //console.log(exists + " " + name); - res.send(JSON.stringify(exists)); + res.send(exists); res.end("yes"); }); diff --git a/backend/config/default.json b/backend/config/default.json index c96bcfb..3f7f2c6 100644 --- a/backend/config/default.json +++ b/backend/config/default.json @@ -7,13 +7,15 @@ "Encryption": { "use-encryption": false, "cert-file-path": "cert.pem", - "key-file-path": "privkey.pem", - "chain-file-path": "chain.pem" + "key-file-path": "privkey.pem" }, "Downloader": { "path-base": "http://localhost:8088/", "path-audio": "audio/", "path-video": "video/" + }, + "Extra": { + "title_top": "Youtube Downloader" } } } \ No newline at end of file diff --git a/src/app/app.component.html b/src/app/app.component.html index e8a94be..1ede66b 100644 --- a/src/app/app.component.html +++ b/src/app/app.component.html @@ -33,7 +33,12 @@
- +
+ +
+ + +
diff --git a/src/app/app.component.ts b/src/app/app.component.ts index 07df85f..0735951 100644 --- a/src/app/app.component.ts +++ b/src/app/app.component.ts @@ -3,6 +3,7 @@ import {PostsService} from './posts.services'; import { Observable } from 'rxjs/Observable'; import {FormControl, Validators} from '@angular/forms'; import {BrowserAnimationsModule} from '@angular/platform-browser/animations'; +import {MatSnackBar} from '@angular/material'; import 'rxjs/add/observable/of'; import 'rxjs/add/operator/mapTo'; import 'rxjs/add/operator/toPromise'; @@ -13,6 +14,7 @@ import 'rxjs/add/operator/toPromise'; styleUrls: ['./app.component.css'] }) export class AppComponent { + determinateProgress: boolean = false; downloadingfile: boolean = false; audioOnly: boolean; urlError: boolean = false; @@ -20,13 +22,15 @@ export class AppComponent { url: string = ''; exists: string = ""; topBarTitle: string = "Youtube Downloader"; - constructor(private postsService: PostsService) { + percentDownloaded: number; + constructor(private postsService: PostsService, public snackBar: MatSnackBar) { this.audioOnly = true; - this.postsService.loadNavItems().subscribe(result => { + this.postsService.loadNavItems().subscribe(result => { // loads settings var backendUrl = result.YoutubeDLMaterial.Host.backendurl; + this.topBarTitle = result.YoutubeDLMaterial.Extra.title_top; this.postsService.path = backendUrl; this.postsService.startPath = backendUrl; @@ -66,9 +70,17 @@ export class AppComponent { downloadHelperMp3(name: string) { this.postsService.getFileStatusMp3(name).subscribe(fileExists => { - this.exists = fileExists; - if (this.exists == "failed") + var exists = fileExists; + this.exists = exists[0]; + if (exists[0] == "failed") { + var percent = exists[2]; + console.log(percent); + if (percent > 0.30) + { + this.determinateProgress = true; + this.percentDownloaded = percent*100; + } setTimeout(() => this.downloadHelperMp3(name), 500); } else @@ -82,9 +94,16 @@ export class AppComponent { downloadHelperMp4(name: string) { this.postsService.getFileStatusMp4(name).subscribe(fileExists => { - this.exists = fileExists; - if (this.exists == "failed") + var exists = fileExists; + this.exists = exists[0]; + if (exists[0] == "failed") { + var percent = exists[2]; + if (percent > 0.30) + { + this.determinateProgress = true; + this.percentDownloaded = percent*100; + } setTimeout(() => this.downloadHelperMp4(name), 500); } else @@ -111,8 +130,11 @@ export class AppComponent { { this.downloadHelperMp3(this.path); } + }, + error => { // can't access server + this.downloadingfile = false; + this.openSnackBar("Download failed!", "OK."); }); - } else { @@ -123,7 +145,11 @@ export class AppComponent { { this.downloadHelperMp4(this.path); } - }); + }, + error => { // can't access server + this.downloadingfile = false; + this.openSnackBar("Download failed!", "OK."); + }); } } else @@ -137,5 +163,11 @@ export class AppComponent { var re=new RegExp(strRegex); return re.test(str); } + + openSnackBar(message: string, action: string) { + this.snackBar.open(message, action, { + duration: 2000, + }); + } } diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts index 7ace913..5859fed 100644 --- a/src/app/posts.services.ts +++ b/src/app/posts.services.ts @@ -55,12 +55,12 @@ export class PostsService { .map(res => res.json()); } - getFileStatusMp3(name: string): Observable { + getFileStatusMp3(name: string): Observable { return this.http.post(this.path + "mp3fileexists",{name: name}) .map(res => res.json()); } - getFileStatusMp4(name: string): Observable { + getFileStatusMp4(name: string): Observable { return this.http.post(this.path + "mp4fileexists",{name: name}) .map(res => res.json()); } diff --git a/src/favicon.ico b/src/favicon.ico index 8081c7c..86ee06e 100644 Binary files a/src/favicon.ico and b/src/favicon.ico differ