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

时间:2021-08-05 16:47:34

I've searched far and wide but couldn't find an appropriate answer for my use-case. Basically I'd like to download a base64-encoded file (could be a pdf, pgn, jpeg - using a pdf in the following example) from my backend, save it to a TEMPORARY fileSystem folder, then open it - possibly using the appropriate app on the device, if present. Let /file be a route served by the following ASP.NET MVC WebAPI Controller:

我搜索了很多地方,但是没有找到适合我用例的答案。基本上,我想从我的后端下载一个base64编码的文件(可以是pdf、pgn、jpeg——在下面的示例中使用一个pdf),保存到一个临时文件系统文件夹中,然后打开它——如果存在的话,可以使用设备上的适当应用程序。让/文件为下列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;
    }

}

I came up with the following AngularJS script:

我想到了下面的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);
    });
};

I'm currently stomped at the loading phase: tried window.opening the base64-encoded content of the file, http.getting the fileEntry.toURL() but nothing seems to work. I checked out Cordova's File Opener 2 plugin but it seems it can only open files stored on the device's sdcard or such. Any clue is welcomed! Cheers.

我目前在加载阶段被踩踏:尝试窗口。打开文件的base64编码内容http。获取文件。tourl()但似乎什么都不管用。我查看了Cordova的文件开启器2插件,但它似乎只能打开设备的sdcard之类的文件。欢迎任何线索!欢呼。

1 个解决方案

#1


3  

FileOpener2 plugin is pretty much you're only option I think - and it can work in this scenario. You'll need to make sure the file is saved outside your app's container on the device, as other apps cannot access this. You can find the file structure for each platform, and what is/isn't public, on the plugin page. You'll also need to save to different locations depending on the platform. This works for me:-

FileOpener2插件几乎是你唯一的选择——它可以在这个场景中工作。您需要确保文件保存在设备上应用程序容器之外,因为其他应用程序无法访问该文件。您可以在插件页面找到每个平台的文件结构,以及什么是/不是公共的。您还需要根据平台将其保存到不同的位置。这适合我:-

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

You can then use storagePath as the base for your targetPath when downloading. I would highly recommend using ngCordova. The sample below is partially based on something that I'm successfully using on iOS and Android but I haven't tested it

然后,您可以在下载时使用storagePath作为目标路径的基础。我强烈推荐使用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
});

#1


3  

FileOpener2 plugin is pretty much you're only option I think - and it can work in this scenario. You'll need to make sure the file is saved outside your app's container on the device, as other apps cannot access this. You can find the file structure for each platform, and what is/isn't public, on the plugin page. You'll also need to save to different locations depending on the platform. This works for me:-

FileOpener2插件几乎是你唯一的选择——它可以在这个场景中工作。您需要确保文件保存在设备上应用程序容器之外,因为其他应用程序无法访问该文件。您可以在插件页面找到每个平台的文件结构,以及什么是/不是公共的。您还需要根据平台将其保存到不同的位置。这适合我:-

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

You can then use storagePath as the base for your targetPath when downloading. I would highly recommend using ngCordova. The sample below is partially based on something that I'm successfully using on iOS and Android but I haven't tested it

然后,您可以在下载时使用storagePath作为目标路径的基础。我强烈推荐使用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
});