1
votes

I have a problem with downloading files from IBM Bluemix Object Storage using NodeJS script, the problem is that it takes very long time to download file from the storage, 100K file takes around 21 seconds, around 8 seconds waiting for the first chunk and rest for reading all the chunks

I am using the service to store images and using NodeJS script read these images from the storage, and the images are downloaded via the HTML img tag, so what exactly I am doing wrong here ?

The nodeJS code:

app.get("/ostore/image/:filename", function(request, response) {
    response.set('Content-Type', 'image/jpg');
    response.set('cache-control', 'max-age=604800');
    response.set('Last-Modified', 'Sat, 05 Dec 2015 03:17:48 GMT');
    var credentials = app.appEnv.services['Object-Storage'][0].credentials
    var pkgcloud = require("pkgcloud");
    var client = pkgcloud.storage.createClient({
        provider: 'openstack',
        username: credentials.userId,
        password: credentials.password,
        authUrl: credentials.auth_url,
        tenantId: credentials.projectId,
        region: credentials.region,
        version: "2"
    });
    client.download({
        container: app.storageContainer,
        remote: request.params.filename,
        stream: response
    }, function() {
        response.end('done');
    });
});
2

2 Answers

1
votes

Try something like this:

routes.js

var vcap_os = require(__dirname + '/../utils/vcap')('Object-Storage'),
    os = require(__dirname + '/../modules/object-storage');

module.exports = function(app) {
    var router = app.loopback.Router();

    // proxy for object storage service
    router.get('/api/Products/image/:container/:file', function(req, res) {
        os(vcap_os.credentials).download(req.params.container, req.params.file, function(download) {
            download.pipe(res);
        });
    });

    app.use(router);
}

modules/object-storage.js

var pkgcloud = require('pkgcloud');

module.exports = function(creds) {
    var config = {
        provider: 'openstack',
        useServiceCatalog: true,
        useInternal: false,
        keystoneAuthVersion: 'v3',
        authUrl: creds.auth_url,
        tenantId: creds.projectId,
        domainId: creds.domainId,
        username: creds.username,
        password: creds.password,
        region: creds.region
    };

    return {
        download: function(container, file, cbk) {
            var client = pkgcloud.storage.createClient(config);
            client.auth(function (error) {
                if(error) {
                    console.error("Authorization error for storage client (pkgcloud): ", error);
                }
                else {
                    var request = client.download({
                        container: container,
                        remote: file
                    });

                    cbk(request);
                }
            });
        }
    };
};
0
votes

Using the answer from joe, and with few modifications, the service is working fine now, I had to change the library pkgcloud as it is causing authentication issues with bluemix and I switched to the wrapper package pkgcloud-bluemix-objectstorage, my code looks like this now:

app.get('/ostore/image/:filename', (request, response) => {
    const credentials = app.appEnv.services['Object-Storage'][0].credentials;
    const config = {};
    config.provider = 'openstack';
    config.authUrl = 'https://identity.open.softlayer.com/';
    config.region = credentials.region;
    config.useServiceCatalog = true;
    config.useInternal = true;
    config.tenantId = credentials.projectId;
    config.userId = credentials.userId;
    config.username = credentials.username;
    config.password = credentials.password;
    config.auth = {
        forceUri: 'https://identity.open.softlayer.com/v3/auth/tokens',
        interfaceName: 'public',
        identity: {
            methods: [
                'password'
            ],
            password: {
                user: {
                    id: credentials.userId,
                    password: credentials.password
                }
            }
        },
        scope: {
            project: {
                id: credentials.projectId
            }
        }
    };

    const client = pkgcloud.storage.createClient(config);
    client.auth(error => {
        if (error) {
            console.error('Authorization error for storage client (pkgcloud): ', error);
        } else {
            const download = client.download({
                container: app.storageContainer,
                remote: request.params.filename
            });
            download.on('response', res => {
                delete res.headers['content-type'];
                delete res.headers['last-modified'];
                res.headers['Last-Modified'] = 'Sat, 05 Dec 2015 03:17:48 GMT';
                res.headers['Cache-Control'] = 'public, max-age=2592000';
                res.headers['Expires'] = new Date(Date.now() + 2592000000).toUTCString();
                res.headers['Content-Type'] = 'image/jpg';
            }).pipe(response);
        }
    });
});