ionic загрузить файл, сохранить во временную файловую систему и открыть с помощью приложения по умолчанию

Я искал повсюду, но не смог найти подходящего ответа для моего варианта использования. По сути, я хотел бы загрузить файл с кодировкой base64 (может быть pdf, pgn, jpeg - используя pdf в следующем примере) из моего бэкэнда, сохранить его в папку TEMPORARY fileSystem, а затем открыть его - возможно, используя соответствующий приложение на устройстве, если оно есть. Пусть /file будет маршрутом, обслуживаемым следующим контроллером ASP.NET MVC WebAPI:

public class FileController : ApiController
{
    // POST api/file/
    public HttpResponseMessage Post([FromBody]string fullPath)
    {
        HttpResponseMessage result = new HttpResponseMessage(HttpStatusCode.OK);
        var stream = new FileStream(fullPath, FileMode.Open);
        result.Content = new StreamContent(stream);
        result.Content.Headers.ContentType = new MediaTypeHeaderValue("application/octet-stream");
        return result;
    }

}

Я придумал следующий скрипт AngularJS:

$scope.download = function(fileName) {
    window.requestFileSystem(window.TEMPORARY, 1024*1024*500, function(fileSystem) {
        fileSystem.root.getDirectory("TempDir", {create: true}, function(dirEntry) {
            dirEntry.getFile(fileName, {create: true, exclusive: false}, function(fileEntry) {
                $http.post("/file", JSON.stringify(fileName), {
                    headers: {Accept: "application/octet-stream"}
                }).success(function(res) {
                    fileEntry.createWriter(function(fileEntryContent) {
                        var blob = new Blob([res], {type: "application/pdf"});
                        fileEntryContent.write(blob);
                        //Now load file
                        $scope.load(fileName);
                    });
                }).error(function(err) {
                    console.warn(err);
                });
            }, function(err) {
                console.warn("getFile failed:", err);
            });
        }, function(err) {
            console.warn("getDirectory failed:", err);
        });
    }, function(err) {
        console.warn("requestFileSystem failed:", err);
    });
};

$scope.download("foo.pdf");

$scope.load = function(fileName) {
    window.requestFileSystem(window.TEMPORARY, 1024*1024*500, function(fileSystem) {
        fileSystem.root.getDirectory("TempDir", {create: false}, function(dirEntry) {
            dirEntry.getFile(fileName, {create: false, exclusive: false}, function(fileEntry) {
                //This is where the magic needs to happen!
            }, function(err) {
                console.warn("getFile failed:", err);
            });
        }, function(err) {
            console.warn("getDirectory failed:", err);
        });
    }, function(err) {
        console.warn("requestFileSystem failed:", err);
    });
};

В настоящее время я топчусь на этапе загрузки: пробовал window.openкодировать содержимое файла в кодировке base64, http.getкодировать fileEntry.toURL(), но, похоже, ничего не работает. Я проверил плагин Cordova File Opener 2, но оказалось, что он может открывать только файлы, хранящиеся на устройстве. SD-карта или что-то подобное. Любая подсказка приветствуется! Ваше здоровье.


person Andrea Aloi    schedule 08.02.2016    source источник


Ответы (1)


Я думаю, что плагин FileOpener2 - это единственный вариант, и он может работать в этом сценарии. Вам необходимо убедиться, что файл сохранен за пределами контейнера вашего приложения на устройстве, так как другие приложения не могут получить к нему доступ. Вы можете найти файловую структуру для каждой платформы, а также то, что является общедоступным, а что нет, на странице плагина. . Вам также нужно будет сохранить в разных местах в зависимости от платформы. Это работает для меня: -

if (ionic.Platform.isIOS()) storagePath = cordova.file.cacheDirectory + "/temp";
else if(ionic.Platform.isAndroid()) storagePath = cordova.file.externalRootDirectory + "/yourapp/temp";

Затем вы можете использовать storagePath в качестве базы для вашего targetPath при загрузке. Я настоятельно рекомендую использовать ngCordova. Приведенный ниже пример частично основан на том, что я успешно использую на iOS и Android, но не проверял.

// add your options here, i.e. any headers you need to add to the request
var options = {};
$cordovaFileTransfer.download(url, targetPath, options, true).then(function(result) {
    //On successful transfer try and extract the file object
    result.file(function (file) {
        var localFile = file.localURL;
        resolveLocalFileSystemURL(localFile, function (entry) {
            var nativePath = entry.toURL();
            // Open in another app, will fail if app doesn't exist that can open the mime type
            $cordovaFileOpener2.open(nativePath, mime).then(function () {
               // Success!
            }, function (err) {
               // Error!
            });
        }, function(error) {
            //handle error here
        });   
    }, function (error) {
        // handle error here 
    });        
}, function (err) {
    //handle error here
});
person JOC    schedule 08.02.2016
comment
Хм, значит ли это, что я не могу использовать API FileSystem и использовать вложенные вызовы window.requestFileSystem => fileSystem.root.getDirectory => dirEntry.getFile, как в моем примере? Поскольку функция $scope.download работает как шарм, другая часть вызывает у меня головную боль! Спасибо за ваш вклад в любом случае! - person Andrea Aloi; 08.02.2016
comment
Возможно, это можно сделать, но вам лучше переписать его, чтобы использовать обертки ngCordova. Я добавлю пример, как только смогу. Вам также нужно будет изменить свой API, чтобы он отвечал на запросы GET, а не на запросы POST (также POST должен использоваться для вставки данных, а не для запроса ресурса). - person JOC; 08.02.2016
comment
Конечно, я могу изменить свой API, чтобы вместо этого использовать глагол GET. Тем временем я попытаюсь реорганизовать свой код, чтобы использовать только оболочки ngCordova, как вы предлагаете. Ваше здоровье. - person Andrea Aloi; 08.02.2016
comment
P.S. Причина, по которой я пытался использовать FileSystem API и избегать плагинов Cordova, заключалась в том, чтобы максимально протестировать его в браузере. - person Andrea Aloi; 08.02.2016
comment
Я обновил свой ответ примером. Если вы хотите запустить в браузере, тогда это ответ может помочь вам, хотя я сам не пробовал. - person JOC; 09.02.2016