Node.js的:在一个GET请求送达文件(APK尤其是)在成功认证尤其是、文件、js、Node

2023-09-11 01:39:14 作者:醉酒鞭名马

好吧,我想成为Node.js的使用在GET请求的成功验证的apk文件。为此,我使用的是形式的API调用:

  GET / APK /用户名=用户放大器;令牌= a_token_goes_here
 

请注意,实际的认证是通过对请求的首部发送的凭据进行(比如用户名和密码出现在那里)。身份验证成功,当我还验证用户的个性化标记是正确的,是时候对我来说,真正服务于文件返回给客户端。为简单起见的$ C $下处理程序的重要组成部分看起来是这样的:

  Peer.find({用户名:request.credentials.peer.username})EXEC(函数(dbError,结果){。
    如果(dbError){
        //处理错误
    }

    如果(结果[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,{
            内容类型:应用程序/ vnd.android.package存档,
            内容长度:stat.size
        });
        VAR readStream = fs.createReadStream(absolutePath);
        readStream.pipe(响应);
        返回回调(空);
    } 其他 {
        //错误处理?
    }
}
 

我的错误code 200返回在服务器控制台上看到的。然而,在客户端,那感觉就好像Ajax调用永远不会结束。这是因为我禁用按钮之前调用正确的Ajax调用,并且我会在通话结束后立即再次激活按钮。此外,我有没有印在浏览器控制台上打印报表。其实有些报表打印,但也许整个2分钟后,然后再次,并非一切。为了测试的目的,我有一个的的文本文件的与内容

 这是你的APK!
 
node.js 接收get请求

这是我担任的apk。有人能指出我什么,我做错了什么?最有可能的,我应该使用不同的功能服务于文件?我们怎样才能强迫客户端保存,我们最终希望从像上面的?

网址服务文件

在这里,有一个次要的问题(最有可能的幼稚):如果试图下载该文件的客户端使用一个特定很蹩脚的连接,会发生什么?这是否意味着在node.js的解决方案code为阻止所有其他来电,直到与低带宽连接的人完成他/她下载APK吗? (我希望不是,它以某种方式返回块什么的)

加入Ajax调用

  $。阿贾克斯({
    键入:GET,
    网址:theURL,
    接受:应用程序/ vnd.android.package存档,
    beforeSend:功能(XHR){
        xhr.withCredentials = TRUE;
        xhr.setRequestHeader(授权,基本+ mem.apk.username +:+ mem.apk.password);
        xhr.setRequestHeader(APP_KEY,mem.component.appKey);
        xhr.setRequestHeader(APP_SECRET,mem.component.appSecret);
    },
    异步:真正的,
    的contentType:应用程序/ vnd.android.package存档,
    成功:功能(数据,textStatus,jqXHR){
        VAR响应=数据;
        的console.log(数据如下:);
        的console.log(数据);
        的console.log(数据结束);
    },
    错误:功能(数据,textStatus,errorThrown){
        VAR响应= JSON.parse(data.responseText);
        的console.log(JSON.stringify(响应));
        警报(response.message);
    },
    跨域:真正的,
    用户名:mem.apk.username,
    密码:mem.apk.password
})。完成(功能(){})。失败(函数(){})。总是(函数(){
    $('#apkButton')丙(已禁用,假)。
});
 

解决方案

防爆preSS具有以下功能:下载文件

  VAR apkFile = THE_ACTUAL_PATH_TO_THE_APK_NOT_UNDER_PUBLIC
如果(!fs.existsSync(apkFile))
    返回res.status(404)。发送('对不起没有这里的APK');

response.download(apkFile);
 

文档下载()在这里的http:// EX pressjs.com / 4X / api.html#res.download 。防爆preSS工作了正确的头提供您要发送的文件名的扩展名为.apk文件。

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');

response.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'.

 
精彩推荐