From 1ebe0ed36c180faf197779c49669a7dfa5e343d4 Mon Sep 17 00:00:00 2001 From: Joel Lonbeck Date: Tue, 8 Nov 2016 14:49:16 -0800 Subject: [PATCH] added download progress callback --- lib/main.js | 26 +++++++++++++++----------- lib/request.js | 12 +++++++++++- mocha_tests/download-test.js | 9 ++++++++- package.json | 2 +- 4 files changed, 35 insertions(+), 14 deletions(-) diff --git a/lib/main.js b/lib/main.js index 32c008f..99b9f2b 100644 --- a/lib/main.js +++ b/lib/main.js @@ -787,9 +787,10 @@ function Client(dbPath, resourceDir, opts) { * @param languageSlug {string} * @param projectSlug {string} * @param resourceSlug {string} + * @param progressCallback {function} receives download progress updates * @returns {Promise.} The new container */ - const downloadContainer = function(languageSlug, projectSlug, resourceSlug) { + const downloadContainer = function(languageSlug, projectSlug, resourceSlug, progressCallback) { // support passing args as an object if(languageSlug != null && typeof languageSlug == 'object') { resourceSlug = languageSlug.resourceSlug; @@ -798,7 +799,7 @@ function Client(dbPath, resourceDir, opts) { } // get the legacy data as if it were a real resource container - return downloadContainer_Future(languageSlug, projectSlug, resourceSlug) + return downloadContainer_Future(languageSlug, projectSlug, resourceSlug, progressCallback) .then(function(path) { // migrate to resource container let resource; @@ -844,9 +845,10 @@ function Client(dbPath, resourceDir, opts) { * @param languageSlug {string} * @param projectSlug {string} * @param resourceSlug {string} + * @param progressCallback {function} receives download progress updates * @returns {Promise.} the path to the downloaded resource container */ - const downloadContainer_Future = function(languageSlug, projectSlug, resourceSlug) { + const downloadContainer_Future = function(languageSlug, projectSlug, resourceSlug, progressCallback) { // support passing args as an object if(languageSlug != null && typeof languageSlug == 'object') { resourceSlug = languageSlug.resourceSlug; @@ -877,7 +879,7 @@ function Client(dbPath, resourceDir, opts) { mkdirp(path.dirname(containerDir)); if(!containerFormat.url) return Promise.reject('Missing resource format url'); - return request.download(containerFormat.url, tempFile); + return request.download(containerFormat.url, tempFile, progressCallback); }) .then(function(response) { if(response.status !== 200) { @@ -1036,13 +1038,15 @@ function Client(dbPath, resourceDir, opts) { // build categories try { let categories = []; - for(let catSlug of container.info.project.categories) { - let existingCat = library.public_getters.getCategory(container.language.slug, catSlug); - let catName = existingCat ? existingCat.name : catSlug; - categories.push({ - slug: catSlug, - name: catName - }); + if(container.info.project.categories) { + for (let catSlug of container.info.project.categories) { + let existingCat = library.public_getters.getCategory(container.language.slug, catSlug); + let catName = existingCat ? existingCat.name : catSlug; + categories.push({ + slug: catSlug, + name: catName + }); + } } container.project.categories = categories; } catch (err) { diff --git a/lib/request.js b/lib/request.js index 9aced44..0e2f7f5 100644 --- a/lib/request.js +++ b/lib/request.js @@ -61,10 +61,12 @@ function read(uri) { * * @param uri {string} the uri to download * @param dest {string} + * @param progressCallback {function} receives progress updates * @returns {Promise.<{}|Error>} the status code or an error */ -function download(uri, dest) { +function download(uri, dest, progressCallback) { "use strict"; + progressCallback = progressCallback || function() {}; var parsedUrl = url.parse(uri, false, true); var makeRequest = parsedUrl.protocol === 'https:' ? https.request.bind(https) : http.request.bind(http); var serverPort = parsedUrl.port ? parsedUrl.port : parsedUrl.protocol === 'https:' ? 443 : 80; @@ -82,6 +84,14 @@ function download(uri, dest) { return new Promise(function (resolve, reject) { var req = makeRequest(options, function (response) { + var size = response.headers['content-length']; + var progress = 0; + + response.on('data', function(chunk) { + progress += chunk.length; + progressCallback(size, progress); + }); + response.pipe(file); file.on('finish', function() { resolve({ diff --git a/mocha_tests/download-test.js b/mocha_tests/download-test.js index a1a3f02..c5a9928 100644 --- a/mocha_tests/download-test.js +++ b/mocha_tests/download-test.js @@ -24,7 +24,14 @@ describe('Download', function() { this.timeout(10000); it('should download a resource container successfully', function() { - return client.downloadResourceContainer('en', 'gen', 'ulb'); + var progressCalled = false; + return client.downloadResourceContainer('en', 'gen', 'ulb', function(size, progress) { + progressCalled = true; + }) + .then(function(container) { + assert.ok(progressCalled); + assert.notEqual(null, container); + }); }); it('should download, close, and reopen a resource container successfully', function() { diff --git a/package.json b/package.json index 2e31849..566f5f0 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "door43-client", - "version": "0.8.7", + "version": "0.8.8", "description": "A client library for interacting with the Door43 Resource API.", "main": "./lib/main.js", "scripts": {