离子下载文件,保存到临时文件系统并使用默认应用程序打开

ionic download file, save to temporary filesystem and open with default app

我进行了广泛的搜索,但找不到适合我的用例的答案。基本上我想从我的后端下载一个 base64 编码的文件(可以是 pdf、pgn、jpeg - 在下面的例子中使用 pdf),将它保存到 TEMPORARY 文件系统文件夹,然后打开它 -可能在设备上使用适当的应用程序(如果存在)。设 /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.opening 文件的 base64 编码内容,http.getting fileEntry.toURL() 但似乎没有任何效果。我查看了 Cordova's File Opener 2 plugin 但它似乎只能打开存储在设备 sdcard 等设备上的文件。欢迎任何线索!干杯。

FileOpener2 插件几乎是您唯一的选择,我认为它可以在这种情况下工作。您需要确保该文件保存在设备上您的应用程序容器之外,因为其他应用程序无法访问它。您可以在 plugin page 上找到每个平台的文件结构,以及 is/isn 和 public 的内容。您还需要根据平台保存到不同的位置。这对我有用:-

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