3

我正在使用 Brackets-shell 为 Windows 和 OSX 构建桌面打包应用程序。在 Brackets shell 上运行的应用程序能够从服务器打开动态生成的 Excel 工作表和 PDF 文件。在普通浏览器中,对文件的请求是在允许用户保存文件的隐藏 iFrame 中完成的。但是,在 Brackets shell 中,不会加载文档。相反,它在 iFrame 中返回以下错误

Failed to load URL http://my.server.com/generate/test.pdf with error (-3)

谁能告诉我如何让 Brackets 下载并将文件保存在本地 FS 上?我已经尝试过brackets.app.openURLInDefaultBrowser 但这不起作用,因为默认窗口没有应用程序使用的身份验证cookie。

谢谢

4

2 回答 2

2

我认为括号壳(还)不支持这 - 似乎基于CEF的应用程序必须专门实现括号壳尚未完成的“下载处理程序”。这个 AppJS 错误注释说的差不多(因为那个 shell 也是基于 CEF 的)。那里使用 Node 进行下载的建议也适用于括号外壳,但是您会遇到与使用openURLInDefaultBrowser().

如果您正在下载纯文本内容,则可以完全使用括号壳的appshell.fs文件 IO API 来完成,这将修复 cookie 的情况。但这些 API 目前只处理 UTF-8 文本。

所以我认为你需要修补括号壳来实现下载功能。起点是实现 aCefDownloadHandler并将其从CefClient::GetDownloadHandler. 看起来 CEF 会为您处理 Save As 对话框(请参阅show_dialog回调的 arg),因此您可能根本不需要编写太多代码。

于 2013-11-10T04:52:41.913 回答
1

这可以使用 Node 查看:https ://github.com/adobe/brackets/wiki/Brackets-Node-Process:-Overview-for-Developers#Architecture

从标题开始: 第 0 步:设置扩展。

总之,您可以在 websocket 上与括号中的节点进行通信。有了这个,您可以动态加载节点模块并执行它们。

现在,如果您不使用 require,这些说明可能会非常繁重。如果您是,请在这里并使用这些说明。如果您不使用 require 您可以“取消”要求代码并删除您需要的内容。我正在进行的一个项目必须这样做,因为我们意识到括号不支持 pdf 下载有多晚。

因此,以下是一些说明,可以将您需要的内容破解到您的应用程序中。同样,这是对一些非常好的代码的解构。

警告:这不漂亮,也不是让这个工作的括号方法。

警告 警告严重

创建你的节点保存模块

这与上述说明中的操作相同,并且仍将使用 require,但它已加载到节点中,因此您不必担心项目的应用程序部分的 require。保存代码类似这样:https ://github.com/joelrbrandt/brackets-simple-node/blob/master/node/SimpleDomain.js

(function () {
    "use strict";
    var url = require('url');
    var http = require('http');
    var https = require('https');
    var fs = require('fs');

    function cmdSaveFileFromUrl(urlString, dest) {
        var requestUrlObject = url.parse(urlString, true);
        var options = {
            hostname: requestUrlObject.hostname,
            port: +requestUrlObject.port,
            path: requestUrlObject.path
        };
        var requester = requestUrlObject.protocol === "http:" ? http : https;
        var file = fs.createWriteStream(dest);
        var request = requester.get(options, function(response) {
            response.on('end', function(){
                file.on('finish', function() {
                    file.close();
                });
            });
            response.pipe(file);
        });
    }

    function init(DomainManager) {
      ...
    }
    exports.init = init;
}());

动态加载此模块

现在您需要获取将动态加载此模块的 appshell 代码。为此,您基本上需要括号中的整个 NodeConnection 模块。该模块负责使 websocket 到节点工作。因此,如果您没有像我一样的要求,您可以“取消”要求它。撕掉导出的东西,让它自己返回,把它包含在你的 index.html 中。

function NodeConnection() {
    "use strict";
....
    return NodeConnection;
}

调用节点连接的代码

最后,您需要使用节点连接来加载模块并发送命令以执行其任务,括号外壳(appshell)再次为此提供模块,但如果您没有要求,您需要提取您需要的内容。实用方法中的大多数方法都可以很容易地取出。https://github.com/joelrbrandt/brackets-simple-node/blob/master/main.js

从任何地方:

function chain() {
    var functions = Array.prototype.slice.call(arguments, 0);
    if (functions.length > 0) {
        var firstFunction = functions.shift();
        var firstPromise = firstFunction.call();
        firstPromise.done(function () {
            chain.apply(null, functions);
        });
    }
}
function connect() {
    var connectionPromise = nodeConnection.connect(true);
    connectionPromise.fail(function () {
        console.error("[brackets-node] failed to connect to node");
    });
    return connectionPromise;
}
function getNativeBracketsDirectoryPath() {
    var pathname = decodeURI(window.location.pathname);
    var directory = pathname.substr(0, pathname.lastIndexOf("/"));
    return convertToNativePath(directory);
}
function convertToNativePath(path) {
    path = unescape(path);
    if (path.indexOf(":") !== -1 && path[0] === "/") {
        return path.substr(1);
    }

    return path;
}
function loadDomain() {
   var root_url = getNativeBracketsDirectoryPath();
   var path = root_url + "/node/YOUR_NODE_MODULE_FROM_STEP_ONE.js";
   var loadPromise = nodeConnection.loadDomains([path], true);
   loadPromise.fail(function () {
       console.log("[brackets-node] failed to load domain");
   });
   return loadPromise;
}
function saveFile(inUrl, path) {
    path = path || window.appshell.app.getUserDocumentsDirectory()+"/file";
    var memoryPromise = nodeConnection.domains.yourdomain.saveFileFromUrl(inUrl, path);
    memoryPromise.fail(function (err) {
        console.error("[brackets-node] failed to run saveFileFromUrl", err);
    });
    memoryPromise.done(function () {
                    console.log("Check the file");
    });
    return memoryPromise;
}
var  NodeConnectionObject = NodeConnection();
var nodeConnection = new NodeConnectionObject();
chain(connect, loadDomain, function(){
   return saveFile(urlToFetch, file)
});

我希望这可以帮助别人。

于 2014-02-17T22:31:05.420 回答