Как мне загрузить файл в приложении-скобке?

Я использую Brackets-shell для создания настольного упакованного приложения для Windows и OSX. Приложение, которое запускается в оболочке Brackets, может открывать динамически сгенерированные листы Excel и файлы PDF с сервера. В обычном браузере запрос к файлу выполняется в скрытом iFrame, который позволяет пользователю сохранить файл. Однако в оболочке скобок документ не загружается. Вместо этого он возвращает следующую ошибку в iFrame

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

Кто-нибудь может подсказать, как заставить Brackets скачать и сохранить файл на локальной ФС? Я уже пробовал brackets.app.openURLInDefaultBrowser, но это не сработает, поскольку в окне по умолчанию нет файлов cookie аутентификации, которые использует приложение.

Спасибо

2 ответа

Я думаю, что это (пока) не поддерживается оболочкой-скобками - похоже, что приложения на основе CEF должны специально реализовывать "обработчик загрузки", который оболочка-скобки не сделала. Этот комментарий об ошибке AppJS говорит примерно то же самое (поскольку эта оболочка также основана на CEF). Предложение использовать для загрузки Node также будет работать с скобками-оболочкой, но вы столкнетесь с той же проблемой с аутентификационными cookie, что и с openURLInDefaultBrowser(),

Если бы вы загружали только текстовый контент, это можно было бы сделать полностью с помощью скобок-оболочки appshell.fs API-интерфейсы файлового ввода-вывода, которые исправят ситуацию с файлами cookie. Но эти API в настоящее время обрабатывают только текст UTF-8.

Поэтому я думаю, что вам нужно будет исправить скобки-оболочки для реализации функции загрузки. Отправной точкой будет реализация CefDownloadHandler и вернуть его из CefClient::GetDownloadHandler, Похоже, CEF позаботится о диалоге Сохранить как для вас ( см. show_dialog arg of callback), так что вам вообще не нужно писать много кода.

Это можно сделать, используя узел просмотра: https://github.com/adobe/brackets/wiki/Brackets-Node-Process:-Overview-for-Developers

начинается вокруг заголовка: Шаг 0: Настройка расширения.

В итоге вы можете общаться с узлом в скобках на веб-сокете. При этом вы можете загружать модули узлов динамически, а также выполнять их.

Теперь эти инструкции могут быть довольно тяжелыми, если вы не используете require. Если да, то остановитесь здесь и используйте эти инструкции. Если вы не используете require, вы можете "un" потребовать код и удалить то, что вам нужно. Проект, над которым я работаю, должен был сделать это, потому что по тому, как поздно мы поняли, что скобки не поддерживают загрузку 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;
}());

динамически загружать этот модуль

Теперь вам нужно получить код приложения, который будет динамически загружать этот модуль. Для этого вам понадобится в основном весь модуль NodeConnection из скобок. Этот модуль отвечает за работу веб-сокета с узлом. Так что если у вас нет необходимости, как я, вы можете "un" требовать этого. разорвите экспорт и просто дайте ему самому вернуться, включите это в ваш 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)
});

Я надеюсь, что это помогает кому-то.

Другие вопросы по тегам