gpt4 book ai didi

java - Apache POI,改变文件 MIME 类型。有可能修复它吗?

转载 作者:塔克拉玛干 更新时间:2023-11-02 19:45:14 24 4
gpt4 key购买 nike

我在使用 Apache POI 和文件 Mime 类型时遇到问题。我使用文件模板 (Microsoft Word DOCX) 通过 Apache Poi 修改一些值。原始文件的 MIME 类型为“application/vnd.openxmlformats-officedocument.wordprocessingml.document”(在 linux 中:file -i {filename}),但是我用 POI 处理文件并保存,然后再次得到“application/octet -stream”,我希望保留原始 mime 类型的文件。

我用 HEX 编辑器打开文件,原始文件和修改后的文件都具有相同的“魔数(Magic Number)”(50 4B 03 04),但文件大小不同,即使文本相同。那么有可能修复它吗?有人有同样的问题吗?我在 LibreOffice 中对其进行了检查,它似乎具有与 Apache POI 相同的行为。

任何帮助,任何信息都会有所帮助。

最佳答案

正如您在评论中所述,Apache POI 重新排列 Office Open XML ZIP 包的方式会导致某些工具误解内容类型。 Office Open XML 文件(*.docx*.xlsx*.pptx)一个ZIP 存档,但有些 Microsoft Office 打包该存档的方式一定很特别。不过我还没有找到它到底是什么。

例子:

开始创建一个包含一些简单内容的 Document.docx,这些内容由 Microsoft Word 保存。

为此,file -i 产生:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ file -i Document.docx 
Document.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=binary

现在运行该代码:

import java.io.FileOutputStream;
import java.io.FileInputStream;

import org.apache.poi.xwpf.usermodel.XWPFDocument;

public class WordReadAndReWrite {

public static void main(String[] args) throws Exception {

String inFilePath = "Document.docx";
String outFilePath = "NewDocument.docx";

XWPFDocument doc = new XWPFDocument(new FileInputStream(inFilePath));

doc.createParagraph().createRun().setText("new text inserted");

FileOutputStream out = new FileOutputStream(outFilePath);
doc.write(out);
out.close();
doc.close();
}

}

对于生成的 NewDocument.docxfile -i 产生:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ file -i NewDocument.docx 
NewDocument.docx: application/octet-stream; charset=binary

但是如果我们在不使用 Apache POI 的 ZipPackage 的情况下做同样的事情而是使用 FileSystem使用以下代码从 Office Open XML ZIP 包中获取 XML:

import java.nio.file.Files;
import java.nio.file.FileSystems;
import java.nio.file.FileSystem;
import java.nio.file.Paths;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.nio.file.StandardOpenOption;

import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.DocumentBuilder;

import org.w3c.dom.Document;
import org.w3c.dom.Node;

import javax.xml.transform.TransformerFactory;
import javax.xml.transform.Transformer;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.dom.DOMSource;

public class WordReadAndReWriteFileSystem {

public static void main(String[] args) throws Exception {

String inFilePath = "Document.docx";
String outFilePath = "NewDocument.docx";

FileSystem fileSystem = FileSystems.newFileSystem(Paths.get(inFilePath), null);
Path wordDocumentXml = fileSystem.getPath("/word/document.xml");

DocumentBuilder documentBuilder = DocumentBuilderFactory.newInstance().newDocumentBuilder();
Document xmlDocument = documentBuilder.parse(Files.newInputStream(wordDocumentXml, StandardOpenOption.READ));

Node p = xmlDocument.createElement("w:p");
Node r = xmlDocument.createElement("w:r");
p.appendChild(r);
Node t = xmlDocument.createElement("w:t");
r.appendChild(t);
Node text = xmlDocument.createTextNode("new text inserted");
t.appendChild(text);

Node body = xmlDocument.getElementsByTagName("w:body").item(0);
Node sectPr = xmlDocument.getElementsByTagName("w:sectPr").item(0);
body.insertBefore(p, sectPr);

TransformerFactory transformerFactory = TransformerFactory.newInstance();
Transformer transformer = transformerFactory.newTransformer();
DOMSource domSource = new DOMSource(xmlDocument);
Path tmpDoc = Files.createTempFile("wordDocument", "tmp");
tmpDoc.toFile().deleteOnExit();
StreamResult streamResult = new StreamResult(Files.newOutputStream(tmpDoc, StandardOpenOption.WRITE));
transformer.transform(domSource, streamResult);

fileSystem.close();

Path tmpZip = Files.createTempFile("zipDocument", "tmp");
tmpZip.toFile().deleteOnExit();
Path path = Files.copy(Paths.get(inFilePath), tmpZip, StandardCopyOption.REPLACE_EXISTING);
fileSystem = FileSystems.newFileSystem(path, null);
wordDocumentXml = fileSystem.getPath("/word/document.xml");

Files.copy(tmpDoc, wordDocumentXml, StandardCopyOption.REPLACE_EXISTING);
fileSystem.close();

Files.copy(tmpZip, Paths.get(outFilePath), StandardCopyOption.REPLACE_EXISTING);

}

}

然后对于生成的 NewDocument.docxfile -i 产生:

axel@arichter:~/Dokumente/JAVA/poi/poi-4.0.1$ file -i NewDocument.docx 
NewDocument.docx: application/vnd.openxmlformats-officedocument.wordprocessingml.document; charset=binary

关于java - Apache POI,改变文件 MIME 类型。有可能修复它吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55398039/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com