WinRT / Metro / WSA问题,为ZipView提供来自ZipArchive的流

时间:2014-03-07 13:13:49

标签: c# webview windows-runtime microsoft-metro windows-store-apps

我需要提供一个包含本地存储的zip文件内容的WebView。

我使用NavigateToLocalStreamUri()方法并提供我自己的扩展UriResolver,方法与Windows库链接NavigateToLocalStreamUri()上的示例相同。

但是,由于“NTLSUri”方法无法识别流的类型并尝试强制转换,因此调试失败的情况相当惊人。有谁知道如何正确地从压缩存档元素提供流到WebView?

以下是详细信息:

这是我自己定制的GetContent()方法,用于为归档元素提供流而不是正常流。

private async Task<IInputStream> GetNormalZipEntryStream(String archivePath)
    {
        StorageFolder current = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFolderAsync("bookTest");

        bookSourceFile = await current.GetItemAsync("testBook.zip") as StorageFile;

        if (archivePath.ElementAt(0) == '/') archivePath = archivePath.Remove(0, 1);

        Stream bookZipStream = await bookSourceFile.OpenStreamForReadAsync();
        ZipArchive bookArchive = new ZipArchive(bookZipStream, ZipArchiveMode.Read);
        ZipArchiveEntry bookContentFile = bookArchive.GetEntry(archivePath);

        if (bookContentFile == null)
            throw new Exception("Invalid archive entry");
        else
        {
            try
            {
                IInputStream stream = bookContentFile.Open().AsInputStream();
                return stream;
            }
            catch (Exception ex)
            {
                var streamConvErr = ex.Message;
            }
        }
        return null;
    }

现在,一切正常,我能够成功获得存档元素的流。我还确认ArchiveElement.Open()方法确实返回了一个包含“未压缩”内容的流。

问题是 - 在幕后 - NAvigateToStreamUri()方法无法接受bookContentFile.Open()返回的IInput流.AsInputStream()。

它会在以下代码部分导致调试器中断:

#if DEBUG && !DISABLE_XAML_GENERATED_BREAK_ON_UNHANDLED_EXCEPTION
        UnhandledException += (sender, e) =>
        {
            if (global::System.Diagnostics.Debugger.IsAttached) global::System.Diagnostics.Debugger.Break();
        };

此时e(例外)声明“无效的演员操作”。

另请注意,在调试期间,在调用AsInputStream()时,stream的类型不像预期的那样:类型为IInputStream,而是类型为System.IO.NetFxToWinRtStreamAdapter.InputStream

扩展对象进一步将非公共成员“ManagedStream”视为System.IO.Compression.DeflateStream类型

我假设有一些方法可以使用DataReader将流转换为内存流,然后转换回IInputstream,但这似乎是违反直觉的,因为提供的AsInpuSream()方法应该按预期工作。

2 个答案:

答案 0 :(得分:1)

似乎没有办法...据我所知......绕过 IInputStream()返回Type: System.IO.NetFxToWinRtStreamAdapter的流。的InputStream

我编写了以下方法,仅使用Windows.Storage.Stream类型手动将字节复制到新流中。 WebView没有任何抱怨,一切正常

private async Task<IInputStream> GetInputStreamFromIOStream(System.IO.Stream stream, long fileSize)
    {
        try
        {
            BinaryReader binReader = new BinaryReader(stream);
            byte[] byteArr = binReader.ReadBytes((int)fileSize);

            var iMS = new InMemoryRandomAccessStream();
            var imsOutputStream = iMS.GetOutputStreamAt(0);
            DataWriter dataWriter = new DataWriter(imsOutputStream);
            dataWriter.WriteBytes(byteArr);

            await dataWriter.StoreAsync();
            await imsOutputStream.FlushAsync();

            return iMS.GetInputStreamAt(0);
        }
        catch(Exception ex)
        {
            //Error Handling here
            return null;
        }
    }

以下列方式为感兴趣的人实施:

        sourceFile = await current.GetItemAsync("zipfileHere.zip") as StorageFile;
        Stream zipStream = await sourceFile.OpenStreamForReadAsync();
        ZipArchive archive = new ZipArchive(zipStream, ZipArchiveMode.Read);
        ZipArchiveEntry contentFile = archive.GetEntry(archivePathVar);

        if (contentFile == null)
            throw new Exception("Invalid archive entry");
        else
        {
            try
            {
                var zipASize = contentFile.Length;
                IInputStream stream = await GetInputStreamFromIOStream(contentFile.Open(), zipASize);

                return stream;
            }
            catch (Exception ex)
            {
                //Some error handling here
            }

        }

答案 1 :(得分:0)

试试这个:

try
{
    IInputStream stream = bookContentFile.Open().AsRandomAccessStream().GetInputStreamAt(0);
    return stream;
}
catch (Exception ex)
{
    var streamConvErr = ex.Message;
}

基本上,这会首先将流转换为Windows运行时等效项,然后使用内置方法获取IInputStream版本。