【问题标题】:WinRT/Metro/WSA issue providing WebView with stream from ZipArchiveWinRT/Metro/WSA 问题为 WebView 提供来自 ZipArchive 的流
【发布时间】:2014-03-07 13:13:49
【问题描述】:

我需要为 WebView 提供本地存储的 zip 文件中的内容。

我使用 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().AsInputStream() 返回的 IInput 流。

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

#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() 时,流的类型与预期不同:IInputStream 类型,而是 System.IO.NetFxToWinRtStreamAdapter.InputStream 类型

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

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

【问题讨论】:

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


    【解决方案1】:

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

    我编写了以下方法来手动将字节复制到新流中,仅使用 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
                }
    
            }
    

    【讨论】:

      【解决方案2】:

      试试这个:

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

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

      【讨论】:

      • 谢谢,但这会(并且确实)抛出Notsupported 异常。 (下面的消息)简而言之:bookContentFile.Open() 返回的流不可搜索。因此,您无法将其作为 IRandomAccess 流获取。 ... 例外:“不能将指定的 Stream 用作 Windows 运行时 IRandomAccessStream,因为此 Stream 不支持查找。”
      • 如果是这种情况,那么您可能确实需要使用StreamReader(或更可能是DataReader)并以这种方式复制内容。稍后我会试试看。
      • 我决定使用 DataReader。我在上面发布了我的解决方案,它可以正常工作......现在。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-14
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-02-22
      • 1970-01-01
      相关资源
      最近更新 更多