首页 > 解决方案 > 使用 Java 从 DOC 文件中提取嵌入式 ZIP

问题描述

我有一个包含多个嵌入文件的 DOC 文件。此文件中嵌入了 PDF、DOC 和 ZIP。我已经使用 Apache POI 来钻取 POIFS。我可以提取 OLE10 文件信息、原始文件名、路径、大小等。

我遇到困难的地方是在从文档中提取 ZIP 文件的过程中。我使用 DocumentInputStream 复制到带有 IOUtils 的 FileOutputStream。

// Load the file object and embedded file system
        File file = new File(filePathBuilder.toString());
        POIFSFileSystem wordDocFS = new POIFSFileSystem(new FileInputStream(file));
        DirectoryNode docRootDir = wordDocFS.getRoot();

        // Read ROOT POIFS
        Iterator<Entry> docRootDirIter = docRootDir.getEntries();
        while(docRootDirIter.hasNext()){
            Entry docRootDirEntry = docRootDirIter.next();

            if (docRootDirEntry.getName().contains("ObjectPool")){
                objPoolDir = (DirectoryNode) docRootDirEntry;

                // Read ObjectPool POIFS directory ---> ObjectPool is location of embedded files within a DOC file
                Iterator<Entry> objPoolDirIter = objPoolDir.getEntries();
                while(objPoolDirIter.hasNext()){
                    Entry objPoolDirEntry = objPoolDirIter.next();

                    // Read ObjectPool POIFS subdirectories
                    if(objPoolDirEntry.isDirectoryEntry()){
                        DirectoryNode objPoolSubDir = (DirectoryNode) objPoolDirEntry;

                        Iterator<Entry> objPoolSubDirIter = objPoolSubDir.getEntries();
                        while (objPoolSubDirIter.hasNext()){
                            Entry objPoolSubDirEntry = objPoolSubDirIter.next();

                            // Read embedded OLE10 files, create an OLE object, and read into an ArrayList of OLE objects
                            if (objPoolSubDirEntry.isDocumentEntry()){
                                DocumentEntry objPoolSubDirFile = (DocumentEntry) objPoolSubDirEntry;

                                if((objPoolSubDirFile.getSize() < 15_000_000)
                                        && (objPoolSubDirFile.getName().contains("Ole10Native"))){

                                    Ole10Native oleEntry = Ole10Native.createFromEmbeddedOleObject(objPoolSubDir);
                                    OleEntry oleObject = new OleEntry();
                                    String oleFqdn = oleEntry.getFileName();

                                    //System.out.println(oleFqdn+"\t"+oleFqdn.endsWith("zip"));
                                    int oleSize = oleEntry.getDataSize();
                                    String olePath = oleFqdn.substring(
                                            0,
                                            oleFqdn.lastIndexOf("\\")+1
                                    );
                                    String oleFilename = oleFqdn.substring(
                                            oleFqdn.lastIndexOf("\\")+1
                                    );
                                    String oleFileType = oleFqdn.substring(
                                            oleFqdn.lastIndexOf(".")+1
                                    );

                                    oleObject.setFileFQDN(oleFqdn);
                                    oleObject.setFilePath(olePath);
                                    oleObject.setFileName(oleFilename);
                                    oleObject.setFileExtension(oleFileType);
                                    oleObject.setFileSize(oleSize);

                                    if(oleObject.getFileName().contains("game_report")){
                                        String streamFileName = "C:\\Users\\ra069466\\Documents\\Software_Projects\\Maint_Tool_test_files\\testOLE\\"
                                                +oleObject.getFileName();

                                        InputStream inStream = new DocumentInputStream(objPoolSubDirFile);
                                        OutputStream outStream = new FileOutputStream(streamFileName);
                                        IOUtils.copy(inStream,outStream);

                                        System.out.println("Wrote out: "
                                                +streamFileName);
                                    }
                                    oleEntryList.add(oleObject);
                                }
                            }
                        }
                    }
                }
            }
        }

它似乎可以复制,但我的操作系统无法将 ZIP 文件识别为存档。

在此处输入图像描述

我尝试将 IOUtils.copy() 设置为输出 ZipOutputStream,但仍然没有成功。我收到“java.util.zip.ZipException:没有当前 ZIP 条目”。我完全不知道如何提取 ZIP 文件并将其写为我可以打开的 ZIP 存档。

标签: javaole

解决方案


@NormR,感谢您的帮助!在第一个 PK 记录之前通过 InputStream.skip() 删除多余的字符解决了这个问题。我能够从 Word DOC 中提取嵌入的 ZIP 文件并将它们写入本地。而且,我现在能够从 ZipFiles 中提取 ZipEntries 以进行正确处理。


推荐阅读