C#OpenFileDialog打开包含单个文件的zip文件夹?

时间:2016-06-02 13:31:03

标签: c# wpf pdf encryption openfiledialog

我有一个应用程序,目前使用户能够使用文件 - >打开,使用Microsoft.Win32.OpenFileDialog浏览到PDF文件的位置,然后显示,在应用程序内查看PDF文件GUI中System.Windows.Controls.WebBrowser的PDF文件。

我正在创建OpenFileDialog并设置可以打开的文件扩展名:

/*Create Open File dialog */
        Microsoft.Win32.OpenFileDialog OFDlg = new Microsoft.Win32.OpenFileDialog();

        /*Set filter for file extension and default file extension */
        OFDlg.DefaultExt = ".pdf";
        OFDlg.Filter = "PDF Documents (.pdf)|*.pdf";

我现在想扩展它,以便用户可以打开包含单个PDF文档的ZIP文件夹,并以与我上面相同的方式显示该PDF文档。

我尝试更改过滤器以允许.zip文件,即

OFDlg.DefaultExt = ".pdf|.zip";
OFDlg.Filter = "PDF Documents (.pdf)|*.pdf|ZIP|*.zip";

但是当我浏览到OpenFileDialog中.zip文件的位置时,.zip文件夹不会显示在那里 - 只有普通文件夹和PDF文档(该目录中的其他文档,例如.doc& ; .xls不会显示在OpenFileDialog)中。

我之所以希望能够直接从.zip打开.zip文件的内容,而不是导航到该文件本身,是因为我可以向.zip添加公钥/私钥加密,所以它的内容只能安全阅读。

我知道如果.zip包含多个文件,理论上可能存在问题,但我打算将每个加密文件发送到自己的zip文件夹中,因此可以假设用户正在尝试的任何zip文件打开包含单个.pdf,没有别的。

所以我的问题是:

  1. 如何从OpenFileDialog看到.zip文件夹?
  2. 如何选择该.zip文件夹自动打开并在我目前用于在我的GUI中显示PDF的System.Window.Controls.WebBrowser中显示其内容(单个PDF文件)?
  3. 修改1

    我尝试将OpenFile()方法更改为以下代码:

    /*Set filter for file extension and default file extension */
            OFDlg.DefaultExt = ".pdf";
            OFDlg.DefaultExt = ".zip";
            OFDlg.Filter = "PDF Documents (.pdf)|*.pdf";
            OFDlg.Filter = "ZIP Folders (.ZIP)|*.zip";
    

    但是当我现在运行我的应用程序并浏览到同一位置时,虽然现在在OpenFileDialog中显示.zip文件夹,但.pdf文件不再是......如果我双击.zip文件夹,我的应用程序中断了,我在行上遇到了运行时错误

    PdfPanel.OpenFile(docFP);
    

    说:

      

    MoonPdfLib.dll中发生未处理的“System.AccessViolationException”类型异常

         

    附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

    我想这与我用来读取无法处理.zip扩展名的PDF的MoonPDF库有关?

    如何解决此问题,以便能够在ZIP中打开PDF?

    修改2

    好的,所以我解决了只能看到PDF文件或.ZIP文件夹(不是同时发生)的问题,方法是将功能转移到两个单独的方法中 - 一个用于显示PDF直接从PDF的文件路径,另一个来显示持有它的.ZIP文件夹路径中的PDF。

    目前直接显示PDF的方法有效(它本质上是我引用的第一位代码中的代码)。但是,从ZIP中显示PDF的方法目前不起作用......

    我理解这个的原因 - 因为我将.zip文件夹传递给OpenFile方法...此方法的代码目前如下所示:

    private void openZipMenuItem_click(object sender, RoutedEventArgs e)
        {
            Microsoft.Win32.OpenFileDialog OZipDlg = new Microsoft.Win32.OpenFileDialog();
    
            OZipDlg.DefaultExt = ".zip";
            OZipDlg.Filter = "ZIP Folder (.zip)|*.zip";
    
            Nullable<bool> result = OZipDlg.ShowDialog();
    
            if (result == true)
            {
                /*Open document */
                string filename = OZipDlg.FileName;
                //fnTextBox.Text = filename;
                zipFP = OZipDlg.FileName;
                /*browser.Navigate(docFP); ERF (27/05/2016 @ 0935) Comment this line- I want to use PdfPanel to open docFP, not browser */
    
                Console.WriteLine("Panel height: " + PdfPanel.ActualHeight);
                PdfPanel.OpenFile(zipFP);
    
            }
        }
    

    当我尝试调用此函数打开.zip时,我得到一个运行时异常,其中包含:

      

    AccessViolationException未处理

         

    MoonPdfLib.dll中发生未处理的“System.AccessViolationException”类型异常

         

    附加信息:尝试读取或写入受保护的内存。这通常表明其他内存已损坏。

    我知道我无法在PdfPanel中显示一个Zip文件夹(我MoonPdfPanel中使用的MoonPdfLibrary),所以我知道我会得到这是一个例外。

    如何将zipFP的内容传递给PdfPanel.OpenFile(),而不是将zipFP本身传递给它?

    编辑3

    好的,所以当我打开它时,我的代码正在从ZIP文件夹中成功提取PDF文件 - 我可以看到它被复制到我指定的目录中。我现在正试图让PDF在我的应用程序的PDF面板中自动显示 - 我已经通过添加以下代码完成了这项工作:

    try{
        string extractPath = @"C:\Documents";
        using(ZipArchivev zip = ZipFile.Open(zipFP, ZipArchiveMode.Read))
            foreach(ZipArchiveEntry entry in zip.Entries){
                try{
                    ZipFile.ExtractToDirectory(zipFP, extractPath);
                    Console.WriteLine("zipFP: " + zipFP);
                }catch(System.IOException){
                    Console.WriteLine("File already exists...");
                }
            }
    
            string ExtractedPDF = string.Concat(extractPath, zipFP);
            PdfPanel.OpenFile(ExtractedPDF);
    }catch(AccessViolationException ex){
        Console.WriteLine("Can't display a zip in the PDF panel..." + ex.InnerException);
    }
    

    但是当我的代码尝试执行第PdfPanel.OpenFile(ExtracedPDF);行时,我得到一个例外:

      

    FileNotFoundException未处理| MoonPdfLib.dll中出现未处理的“System.IO.FileNotFoundException”类型异常

    我理解这种情况正在发生,因为我试图在PDFPanel中显示的变量,ExtractedPDF实际上保存了包含PDF的文件夹的路径,而不是PDF本身 - 我如何给它命名PDF格式的文件,当我实际上不知道将调用什么PDF文件时?

3 个答案:

答案 0 :(得分:1)

这是与你的请求类似的东西,代码背后的逻辑是:

  • 仅在OpenFileDialog
  • 中显示zip和pdf文件
  • 如果用户选择了pdf文件,请在面板中显示
  • 如果用户选择了zip文件,请将OpenFileDialog的目录更改为zip文件(将其视为文件夹)

示例代码(工作代码....):

 OpenFileDialog ofd = new OpenFileDialog();
 ofd.Filter = "PDF files (.pdf)|*.pdf;*.zip";
 ofd.ShowDialog();

 //reopen OpenFileDialog if it is zip file. this part can be improved.
 if (ofd.FileName.EndsWith(".zip")) 
 {
     ofd.InitialDirectory = ofd.FileName;
     ofd.ShowDialog();
 }

 //if it's a PDF, note that you don't really need this check, 
 //as the only file can reache here will be a PDF, 
 //and it can be the temporary file that inside a zip. 
 if(ofd.FileName.EndsWith(".pdf"))
 {
    //show it in your PdfPanel
 }

根据您的新评论和添加的代码进行修改。您需要将代码更改为以下内容,因为当前代码与文件的目录错误:

try{
    string extractPath = @"C:\Documents";
    string ExtractedPDF ="";
    using(ZipArchivev zip = ZipFile.Open(zipFP, ZipArchiveMode.Read))
        foreach(ZipArchiveEntry entry in zip.Entries){
            try{
                ExtractedPDF= Path.Combine(extractPath, entry.FullName);
                entry.ExtractToFile(ExtractedPDF,true);

            }catch(System.IOException){
                Console.WriteLine("error during extraction...");
            }
        } 
        if( System.IO.File.Exists(ExtractedPDF))
        {
             PdfPanel.OpenFile(ExtractedPDF);
        }
}catch(AccessViolationException ex){
    Console.WriteLine("Can't display a zip in the PDF panel..." + ex.InnerException);
}

答案 1 :(得分:1)

如果要在打开的文件对话框中支持多种文件格式,则需要添加第三个(或更好的第一个)选项,以聚合所有支持的文件扩展名:

OFDlg.Filter = "Supported file formats|*.pdf;*.zip|PDF Documents|*.pdf|ZIP files|*.zip";

答案 2 :(得分:0)

首先,关于在打开文件对话框中显示文件。您执行此操作的初始方法是正确的。您现在更新的代码首先将过滤器设置为显示PDF,然后将该过滤器替换为显示zip文件的过滤器。标准文件打开对话框不是为了同时显示不同的文件类型而设计的。处理它的正确方法是为用户提供他们想要显示的文件类型的选项。

通常,还会添加“所有文件”选项(使用作为搜索模式)。这样,如果列表中没有用户想要打开的文件类型,他们就可以看到它。

至于打开zip文件中的PDF文件,您需要自己提取PDF文件。 This question有一些选项可供选择。