node.js:在获取请求上成功验证后,提供文件(特别是apk)

时间:2015-01-20 22:23:52

标签: ajax node.js file rest authentication

好吧,我试图在成功验证get请求后使用node.js提供apk文件。为此,我正在使用以下形式的api调用:

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

请注意,实际身份验证是通过在请求标头上发送凭据来执行的(例如,在那里显示用户名和密码)。身份验证成功,当我还验证用户的个性化令牌是否正确时,我现在是时候将文件实际提供给客户端了。为简单起见,处理程序代码的关键部分如下所示:

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 ...
    }
}

我可以在服务器控制台上看到返回错误代码200。但是,在客户端,感觉好像ajax调用永远不会结束。这是因为我在通话之前禁用了ajax通话的按钮,我将在通话结束后立即再次激活该按钮。此外,我在浏览器控制台上有未打印的打印语句。实际上有些陈述是印刷的,但也许是整整两分钟,然后又一次,而不是一切。出于测试目的,我有一个文本文件,内容为

Here is your APK!

我担任apk。有人能指出我做错了什么吗?我很可能应该使用不同的函数来提供文件?我们如何强制客户端保存我们最终想要提供的文件来自上面的网址?

这里有一个次要问题(很可能是天真的):如果尝试下载文件的客户端使用非常糟糕的连接,会发生什么?这是否意味着node.js上的解决方案代码阻止所有其他传入调用,直到具有低带宽连接的人完成他/她的apk下载? (我希望不会,它以某种方式返回为块或其他东西)

添加ajax调用

$.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);
});

1 个答案:

答案 0 :(得分:1)

Express具有下载文件的功能

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

response.download(apkFile);

下载()的文档在http://expressjs.com/4x/api.html#res.download。如果您发送的文件名的扩展名为“.apk”,则Express会输出正确的标题。