From bdb6a082745c999690338fca26b6b64289e69390 Mon Sep 17 00:00:00 2001 From: Isaac Grynsztein Date: Tue, 17 Mar 2020 22:24:52 -0400 Subject: [PATCH] Added ability to download subscription videos as zip --- backend/app.js | 37 +++++++++++++------ src/app/posts.services.ts | 7 ++-- .../subscription/subscription.component.html | 1 + .../subscription/subscription.component.scss | 20 ++++++++++ .../subscription/subscription.component.ts | 18 +++++++++ 5 files changed, 69 insertions(+), 14 deletions(-) diff --git a/backend/app.js b/backend/app.js index 9fbecb9..a02a6cd 100644 --- a/backend/app.js +++ b/backend/app.js @@ -358,10 +358,16 @@ function getVideoFormatID(name) } } -async function createPlaylistZipFile(fileNames, type, outputName) { +async function createPlaylistZipFile(fileNames, type, outputName, fullPathProvided = null) { return new Promise(async resolve => { - let zipFolderPath = path.join(__dirname, (type === 'audio') ? audioFolderPath : videoFolderPath); - // let name = fileNames[0].split(' ')[0] + fileNames[1].split(' ')[0]; + let zipFolderPath = null; + + if (!fullPathProvided) { + zipFolderPath = path.join(__dirname, (type === 'audio') ? audioFolderPath : videoFolderPath); + } else { + zipFolderPath = path.join(__dirname, config_api.getConfigItem('ytdl_subscriptions_base_path')); + } + let ext = (type === 'audio') ? '.mp3' : '.mp4'; let output = fs.createWriteStream(path.join(zipFolderPath, outputName + '.zip')); @@ -381,7 +387,8 @@ async function createPlaylistZipFile(fileNames, type, outputName) { for (let i = 0; i < fileNames.length; i++) { let fileName = fileNames[i]; - archive.file(zipFolderPath + fileName + ext, {name: fileName + ext}) + let file_path = !fullPathProvided ? zipFolderPath + fileName + ext : fileName; + archive.file(file_path, {name: fileName + ext}) } await archive.finalize(); @@ -1141,9 +1148,6 @@ app.post('/api/getSubscription', async (req, res) => { } else { res.sendStatus(500); } - - - }); app.post('/api/downloadVideosForSubscription', async (req, res) => { @@ -1278,11 +1282,12 @@ app.post('/api/deleteMp4', async (req, res) => { app.post('/api/downloadFile', async (req, res) => { let fileNames = req.body.fileNames; - let is_playlist = req.body.is_playlist; + let zip_mode = req.body.zip_mode; let type = req.body.type; let outputName = req.body.outputName; + let fullPathProvided = req.body.fullPathProvided; let file = null; - if (!is_playlist) { + if (!zip_mode) { fileNames = decodeURIComponent(fileNames); if (type === 'audio') { file = __dirname + '/' + audioFolderPath + fileNames + '.mp3'; @@ -1293,10 +1298,20 @@ app.post('/api/downloadFile', async (req, res) => { for (let i = 0; i < fileNames.length; i++) { fileNames[i] = decodeURIComponent(fileNames[i]); } - file = await createPlaylistZipFile(fileNames, type, outputName); + file = await createPlaylistZipFile(fileNames, type, outputName, fullPathProvided); } - res.sendFile(file); + res.sendFile(file, function (err) { + if (err) { + next(err); + } else if (fullPathProvided) { + try { + fs.unlinkSync(file); + } catch(e) { + console.log("ERROR: Failed to remove file", file); + } + } + }); }); app.post('/api/deleteFile', async (req, res) => { diff --git a/src/app/posts.services.ts b/src/app/posts.services.ts index 6ea4133..97b63de 100644 --- a/src/app/posts.services.ts +++ b/src/app/posts.services.ts @@ -114,11 +114,12 @@ export class PostsService { return this.http.post(this.path + 'getMp4s', {}); } - downloadFileFromServer(fileName, type, outputName = null) { + downloadFileFromServer(fileName, type, outputName = null, fullPathProvided = null) { return this.http.post(this.path + 'downloadFile', {fileNames: fileName, type: type, - is_playlist: Array.isArray(fileName), - outputName: outputName}, + zip_mode: Array.isArray(fileName), + outputName: outputName, + fullPathProvided: fullPathProvided}, {responseType: 'blob'}); } diff --git a/src/app/subscription/subscription/subscription.component.html b/src/app/subscription/subscription/subscription.component.html index 86ece5a..44ccb41 100644 --- a/src/app/subscription/subscription/subscription.component.html +++ b/src/app/subscription/subscription/subscription.component.html @@ -42,4 +42,5 @@ + \ No newline at end of file diff --git a/src/app/subscription/subscription/subscription.component.scss b/src/app/subscription/subscription/subscription.component.scss index a9c26bb..7734644 100644 --- a/src/app/subscription/subscription/subscription.component.scss +++ b/src/app/subscription/subscription/subscription.component.scss @@ -38,7 +38,27 @@ display: block; position: relative; } + .col { width: 33%; display: inline-block; +} + +.spinner { + width: 50px; + height: 50px; + bottom: 3px; + left: 3px; + position: absolute; +} + +.save-button { + right: 25px; + position: absolute; + bottom: 25px; +} + +.save-icon { + bottom: 1px; + position: relative; } \ No newline at end of file diff --git a/src/app/subscription/subscription/subscription.component.ts b/src/app/subscription/subscription/subscription.component.ts index f9ff060..496f2d1 100644 --- a/src/app/subscription/subscription/subscription.component.ts +++ b/src/app/subscription/subscription/subscription.component.ts @@ -41,6 +41,7 @@ export class SubscriptionComponent implements OnInit { } }; filterProperty = this.filterProperties['upload_date']; + downloading = false; constructor(private postsService: PostsService, private route: ActivatedRoute, private router: Router) { } @@ -122,4 +123,21 @@ export class SubscriptionComponent implements OnInit { this.filterByProperty(this.filterProperty['property']); } + downloadContent() { + const fileNames = []; + for (let i = 0; i < this.files.length; i++) { + fileNames.push(this.files[i].path); + } + + this.downloading = true; + this.postsService.downloadFileFromServer(fileNames, 'video', this.subscription.name, true).subscribe(res => { + this.downloading = false; + const blob: Blob = res; + saveAs(blob, this.subscription.name + '.zip'); + }, err => { + console.log(err); + this.downloading = false; + }); + } + }