MemoryStream与FileStream:Document Viewer成功地从文件流中呈现文档而不是内存流?

时间:2011-08-03 15:51:56

标签: c# silverlight pdf stream streaming

我在Silverlight应用程序中使用C1的PDF查看器控件,并且正在测试最大PDF大小限制。 我有一个35MB的PDF。

当我通过OpenFileDialog加载PDF查看器时,只需将文件流发送给它就可以了。全部900页。

但是,当我尝试通过从byte []创建的MemoryStream加载PDF查看器时,它什么都不呈现。它不会出错,只是呈现空白。

这是完全相同的文件。 MemoryStream流程可以与小得多的PDF文档一起成功运行。然而,FileStream方法适用于较大的文档,所以我知道它不是PDF查看器的限制,对吗?

FileStream方法:

        OpenFileDialog ofd = new OpenFileDialog();
        bool? res = ofd.ShowDialog();
        if (res == true)
        {
            FileStream stream = ofd.File.OpenRead();
            docViewer.LoadDocument(stream);
        }

MemoryStream方法:

       imageBytes = File.ReadAllBytes(path);
       MemoryStream stream = new MemoryStream();
       stream.Write(imageBytes, 0, imageBytes.Length);
       stream.Seek(0, SeekOrigin.Begin);
       docViewer.LoadDocument(stream);

这给了我相同的结果。空白观察者:

using (MemoryStream stream = new MemoryStream(imageBytes))
{
      docViewer.LoadDocument(stream);
}

再次......失败感到沮丧。 我重构了使用“OpenReadAsync”的调用,然后我改变了我的API调用(我们使用MVC作为伪API)来返回流并且它仍然呈现为空白。 结果内部流的长度也是正确的。

客户来电:

        string url = App.Server + "Document/RetrievePDFTest";
        try
        {
            WebClient wc = new WebClient();
            wc.OpenReadCompleted += new OpenReadCompletedEventHandler(delegate(object sender, OpenReadCompletedEventArgs e)
            {
                if (e.Result != null)
                {
                    docViewer.LoadDocument(e.Result);
                }
            });
            wc.OpenReadAsync(new Uri(url));
        }
        catch (Exception ex)
        {
            //TODO - handle exception
        }

服务器API:

    public ActionResult RetrievePDFTest()
    {
        return File(System.IO.File.ReadAllBytes("D://temp//repositories//test35mb.PDF"), "application/pdf");
    }

UPDATE !!!! 我相信我发现了可能存在的问题。

在我的silverlight应用程序中,我实际上是在一个新窗口中弹出这个文档查看器,然后我正在向新窗口发送从服务器检索PDF图像的信息。本质上,我告诉它通过我传递的密钥检索哪个文件:

this.windowManager.NavigateToPageInNewWindow("/Views/pdfViewerUserControl.xaml");
                LocalMessageSender s = new LocalMessageSender("receiver", LocalMessageSender.Global);
                s.SendAsync(doc.Barcode);

现在,在我的pdfViewerUserControl.xaml中,在它的构造函数中,我正在创建并注册消息的监听器:

public pdfViewerUserControl()
    {
        LocalMessageReceiver messageReceiver = new LocalMessageReceiver("receiver", ReceiverNameScope.Global, LocalMessageReceiver.AnyDomain);
        messageReceiver.MessageReceived += messageReceiver_MessageReceived;
        try
        {
            messageReceiver.Listen();
        }
        catch (Exception ex)
        {

        }

        // Required to initialize variables
        InitializeComponent();
    }

在“messageReceiver_MessageReceived”事件处理程序中,这是我进行服务器调用以检索图像并加载查看器的地方。即使服务器返回图像,此过程也会生成一个空白的PDF查看器。 (即使是大型pdf)

现在,作为一个测试工具,我在页面上也有一个测试按钮,这个按钮触发后面代码中的一个事件,使得完全相同的服务器调用,并以完全相同的方式加载结果,但这可行! !大型35MB PDF在查看器中成功呈现。

这使我相信使用LocalMessageSender / LocalMessageReceiver对象时会出现断开连接。

3 个答案:

答案 0 :(得分:2)

鉴于评论,我怀疑问题是你将它作为字符串下载然后将其转换为字节。将字节数组中的数据与文件中的数据进行比较(例如,采用MD5哈希)。

要下载二进制数据,您应该使用DownloadData代替。

答案 1 :(得分:0)

一个可能的原因可能是内存流对象必须在最后处理。

using (MemoryStream ms = new MemoryStream())
{
    // Do something with ms..
}

或在使用内存流对象

结束时这样说
stream.Dispose();
stream.Close();

答案 2 :(得分:0)

似乎该问题与查看器或PDF文件完全无关。它与一些无法在我所处的环境中操纵UI的问题有关。

我正在使用HtmlPage.PopupWindow()弹出一个新窗口,指定另一个usercontrol(我的pdf XAML用户控件,其中包含pdfviewer)作为URI。

为了将新窗口传递给要检索/查看的文档的键,我在该新窗口的用户控件上注册了一个监听器。 然后我给那个听众发了钥匙。

在收听者的消息接收事件中,我正在调用获取字节数组并填充查看器。

这似乎没有更新UI。相反,我已经抛弃了监听器/发送器模式,只是将密钥添加到URI的末尾“HtmlPage.PopupWindow()”。 然后在新用户控制页面的构造函数中,我从URI中推断出密钥并且“bob是你的叔叔”,它可以工作。

我仍然不确定我是在一个单独的线程上,还是听众的“收到消息”事件发生了什么。 我在侦听器中遇到断点,文档查看器的“LoadDocument()”方法没有错误我们或抛出异常,UI只是没有呈现更新。