移动服务+ DocumentDB附件

时间:2015-11-03 16:11:10

标签: node.js azure azure-mobile-services azure-cosmosdb

这是我的堆栈:

  • iOS和Android应用

  • DocumentDB

  • 由Javascript支持的移动服务

  • 由Javascript支持的Azure网站

我们要做的是从我们的应用程序中抽象出DocumentDB的知识,因为我们正在构建白标解决方案,我们可能需要即时扩展DocumentDB实例。使用抽象类型的服务,我们基本上可以根据应用程序发送的某些数据对我们的docdb实例进行分片。

现在,这将包含2个我想为其创建移动服务的操作。一个用于获取JSON数据,另一个用于获取与文档关联的附件。这是我的麻烦所在。我有一个可部署的NodeJS编写的传递服务。我喜欢与移动服务相关的安全模型,所以我想调整我的代码。问题在于管理DocDB对移动服务响应的响应。首先是移动服务默认标头试图设置和失败,所以我暂时覆盖该功能。现在,移动服务永远不会响应,直到发生超时。这是一段代码:

exports.get = function (req, res) {
...
// .then().fail() always pushed into the fail() block, but if I use the 2 function in .then() way it works.
client.readMediaAsync(mediaUrl).then(
    // Success
    function (media) {
        // Set up caching and proxy the response
        media.headers["cache-control"] = "max-age=2147483647, max-stale=2147483647";
        media.headers["pragma"] = "cache";
        for (var responseHeader in media.headers) {
            if (media.headers.hasOwnProperty(responseHeader) && "content-location" != responseHeader) {
                res.setHeader(responseHeader, media.headers[responseHeader]);
            }
        }
        // Block further header modification
        res.setHeader = function(field, val){};
        media.result.pipe(res, {end: true});
        //media.result.on("end", function () {
        //    console.log("attachment#end");
        //    res.status(200).send(); // have also tried .end() with no luck
        //});
    },

    // Error
    function (mediaError) {
        console.error("documentClient.readMediaAsync fail->" + JSON.stringify(mediaError));
        res.status(400).send(JSON.stringify(mediaError));
    }
); ...

读取media.result.pipe(...)的行是挂断的地方。同样,此代码在移动服务之外工作。我一直在使用这个改变 - >提交 - >测试 - >重复循环,但没有运气。有人知道如何在流媒体服务中正确地将流传输到响应中吗?

2 个答案:

答案 0 :(得分:0)

我成功地重现了你的问题,我在请求一段时间后得到了HTML代码,但是我在LOGS选项卡中也收到了错误消息,它看起来像:

  

An unhandled exception occurred. Error: Can't set headers after they are sent. at ServerResponse.OutgoingMessage.setHeader (http.js:679:11) at ServerResponse.res.setHeader (D:\home\site\wwwroot\node_modules\express\node_modules\connect\lib\patch.js:59:22) at ServerResponse.res.set.res.header (D:\home\site\wwwroot\node_modules\express\lib\response.js:518:10) at addDefaultHeaders (D:\home\site\wwwroot\runtime\request\requesthandler.js:582:9) at ServerResponse.<anonymous> (D:\home\site\wwwroot\runtime\request\requesthandler.js:291:13) at ServerResponse._.wrap [as end] (D:\home\site\wwwroot\node_modules\underscore\underscore.js:692:22) at onend (stream.js:66:10) at EventEmitter.emit (events.js:126:20) at afterRead (fs.js:1335:12) at Object.wrapper [as oncomplete] (fs.js:367:17)

根据这个日志,我在管道之前将头部设置为响应,并且在我的测试中工作正常。

这是我的简单代码段: exports.get = function(request, response) { var fs = require("fs"); response.setHeader = function(field, val){}; fs.createReadStream('files/123.txt').pipe(response,{end: true}); };

答案 1 :(得分:0)

我通过使用节点documentdb sdk的非承诺版本解决了这个问题。必须有一些东西在答案中与承诺相混淆(虽然它看起来非常简单)。

以下是正常运行的代码段: clientSync.readMedia(mediaUrl, function (err, mediaStream) { if (!err && mediaStream) { mediaStream.headers["cache-control"] = "max-age=2147483647, max-stale=2147483647"; mediaStream.headers["pragma"] = "cache"; for (var responseHeader in mediaStream.headers) { if (mediaStream.headers.hasOwnProperty(responseHeader) && "content-location" != responseHeader) { res.setHeader(responseHeader, mediaStream.headers[responseHeader]); } } res.setHeader = function (field, val) { }; mediaStream.pipe(res); mediaStream.on('end', function () { res.status(200).end(); }); } else { console.error("attachment(" + mediaUrl + ") catch->" + JSON.stringify(err.detail) + "; " + err.message + "; " + err.stack); res.status(400).send(); } });