简体   繁体   中英

node.js: serve a file (apk in particular) upon successful authentication on a get request

Alright, I am trying to serve an apk file using node.js upon successful authentication of a get request. For this purpose I am using an api call of the form:

GET /apk/?username=user&token=a_token_goes_here

Note that the actual authentication is performed by sending the credentials on the header of the request (say a username and password appear there). Authentication succeeds, and when I also verify that the personalized token of the user is correct it is time for me to actually serve the file back to the client. For the sake of simplicity the critical part of the code for the handler looks like this:

Peer.find({"username": request.credentials.peer.username}).exec(function (dbError, results) {
    if (dbError) {
        // handle error
    }

    if (results[0]._id.toString() === request.query.token) {
        var absolutePath = THE_ACTUAL_PATH_TO_THE_APK_NOT_UNDER_PUBLIC;
        var stat = fs.statSync(absolutePath);
        response.writeHead(200, {
            'Content-Type': 'application/vnd.android.package-archive',
            'Content-Length': stat.size
        });
        var readStream = fs.createReadStream(absolutePath);
        readStream.pipe(response);
        return callback (null);
    } else {
        // error handling ...
    }
}

I can see on the server console that the error code 200 is returned. However, on the client side, it feels as if the ajax call never ended. This is so because I disable the button for the ajax call right before the call, and I am going to activate the button again right after the end of the call. Moreover, I have print statements on the browser console that are not printed. Actually some of the statements are printed but perhaps 2 whole minutes later and then again, not everything. For the purposes of testing I have a text file with the contents

Here is your APK!

that I serve as the apk. Can someone point me what I am doing wrong? Most likely I should serve the file using a different function? How can we force the client to save the file that we ultimately want to serve from a url like the one above?

Here, there is a secondary issue (most likely naive): What happens if the client that is trying to download the file does so using a very crappy connection? Does this mean that the solution code on node.js is blocking all other incoming calls until the guy with the low bandwidth connection finishes his/her download of the apk? (I hope not and it is somehow returned as chunks or something)

Addition of the ajax call

$.ajax({
    type: "GET",
    url: theURL,
    accepts: "application/vnd.android.package-archive",
    beforeSend : function(xhr) {
        xhr.withCredentials = true;
        xhr.setRequestHeader("Authorization", "Basic " + mem.apk.username + ":" + mem.apk.password);
        xhr.setRequestHeader("APP_KEY", mem.component.appKey);
        xhr.setRequestHeader("APP_SECRET", mem.component.appSecret);
    },
    async: true,
    contentType: "application/vnd.android.package-archive",
    success: function(data, textStatus, jqXHR) {
        var response = data;
        console.log ("Data follows:");
        console.log (data);
        console.log ("Data ended");
    },
    error: function (data, textStatus, errorThrown) {
        var response = JSON.parse(data.responseText);
        console.log (JSON.stringify(response));
        alert(response.message);
    },
    crossDomain: true,
    username: mem.apk.username,
    password: mem.apk.password
}).done(function() {}).fail(function() {}).always(function() {
    $('#apkButton').prop("disabled",false);
});

Express has a function to download files

var apkFile = THE_ACTUAL_PATH_TO_THE_APK_NOT_UNDER_PUBLIC
if(!fs.existsSync(apkFile))
    return res.status(404).send('Sorry no APKs here');
               
res.download(apkFile);

Documentation for download() is here http://expressjs.com/4x/api.html#res.download . Express works out the correct headers provided the extension of the filename you are sending is '.apk'.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM