解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co

目录

问题描述 

原因分析:

解决方案:

其他问题


问题描述 

使用poi读取用户导入的excel产生的错误,初步判断是用户用的某个软件保存的excel文件有问题,错误信息如下: 

OPC Compliance error [M4.3]: Producers shall not create a document element that contains refinements to the Dublin Core elements, except for the two specified in the schema: and Consumers shall consider a document element that violates this constraint to be an error.

译文:

OPC合规性错误[M4.3]:生产者不得创建包含对Dublin Core元素的细化的文档元素,除了模式中指定的两个元素:dcterms:created和dcterms:modified消费者应该将违反此约束的文档元素视为错误


原因分析:

报错信息中指违反了OPC合规性,去了解一番后大致原因是因为excel文件的元数据导致的,那什么是元数据呢?其实就是作者信息或者是创建时间等信息,一开始想着如果是元数据导致的,那么把元数据删除就好了,但是发现行不通,poi还是读取不了,之后再深入探索一番之后才发现,这个文件居然有两份保存元数据的xml,难怪会报这个问题,那么我是怎么找出来的呢?请往下看.


解决方案:

解决方案就是把多余的xml删除就好了,往下看:

首先需要一个能解压zip的工具,比如WinRAR.如下我的1111.xlsx文件poi是无法读取的,先尝试解压出来:

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第1张图片

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第2张图片

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第3张图片

 解压出来的文件看不懂没关系,我们只需要看docProps这个文件夹就行了,这里面放的就是文件当中的元数据,让我们看看里面是怎么样的:

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第4张图片

将多余的文件删掉之后我们将它打包回xlsx文件格式,这样poi就能正常读取了 

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第5张图片

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第6张图片

 解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第7张图片

 接着再使用poi读取改文件就不会报那个问题了

当然也可直接代码修复:

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipArchiveOutputStream;
import org.apache.commons.io.FileUtils;

public class RepairExcel {

    public static void main(String[] args) throws IOException {
        // 使用
        repair("xlsx文件路径", "指定一个临时即可目录");
    }

    /**
     * 修复
     *
     * @param xlsxFilePath xlsx文件路径
     * @throws IOException ioexception
     */
    public static void repair(String xlsxFilePath, String tempDirPath) throws IOException {
        // 解压 zip 文件
        unzip(xlsxFilePath, tempDirPath);
        // 压缩文件
        addToZip(tempDirPath, xlsxFilePath);
        // 删除解压后的文件
        deleteFolder(new File(tempDirPath));
    }

    /**
     * 解压 zip 文件
     *
     * @param zipFilePath     压缩文件路径
     * @param destDirPath     解压后文件存放目录
     */
    private static void unzip(String zipFilePath, String destDirPath) {
        try (ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath))) {
            ZipEntry entry = zipIn.getNextEntry();
            while (entry != null) {
                String filePath = destDirPath + File.separator + entry.getName();
                if (!entry.isDirectory()) {
                    // Check if the file name matches the filter condition
                    if (!filePath.endsWith("core0.xml")) {
                        extractFileFromZip(filePath, zipIn);
                    }
                } else {
                    File dir = new File(filePath);
                    dir.mkdir();
                }
                zipIn.closeEntry();
                entry = zipIn.getNextEntry();
            }
        } catch (IOException e) {
            System.out.println("Failed to unzip file: " + e.getMessage());
        }
    }

    /**
     * 从zip提取文件
     *
     * @param filePath 文件路径
     * @param zipIn    ZipInputStream
     * @throws IOException ioexception
     */
    private static void extractFileFromZip(String filePath, ZipInputStream zipIn) throws IOException {
        byte[] buffer = new byte[1024];
        File parentDir = new File(filePath).getParentFile();
        if (!parentDir.exists()) {
            parentDir.mkdirs();
        }
        try (FileOutputStream fos = new FileOutputStream(filePath)) {
            int len;
            while ((len = zipIn.read(buffer)) > 0) {
                fos.write(buffer, 0, len);
            }
        }
    }

    /**
     * 添加到zip
     *
     * @param sourceFilePath 源文件路径
     * @param destFilePath   压缩后文件存放目录
     * @throws IOException ioexception
     */
    private static void addToZip(String sourceFilePath, String destFilePath) throws IOException {
        // 1. 创建ZipArchiveOutputStream对象,指定压缩后的输出路径及文件名
        try(ZipArchiveOutputStream zipOut = new ZipArchiveOutputStream(new FileOutputStream(destFilePath))) {
            // 2. 获取需要压缩的文件列表
            List fileList = (List) FileUtils.listFiles(new File(sourceFilePath), null, true);

            // 3. 遍历文件列表,将文件压缩到ZipArchiveOutputStream中
            for (File file : fileList) {
                String fileName = file.getAbsolutePath().substring(sourceFilePath.length() + 1);
                ZipArchiveEntry entry = new ZipArchiveEntry(file, fileName);
                zipOut.putArchiveEntry(entry);
                FileInputStream fileIn = new FileInputStream(file);
                byte[] buffer = new byte[1024];
                int len;
                while ((len = fileIn.read(buffer)) != -1) {
                    zipOut.write(buffer, 0, len);
                }
                fileIn.close();
                zipOut.closeArchiveEntry();
            }
        }
    }

    /**
     * 删除文件夹
     *
     * @param folder 文件夹
     */
    private static void deleteFolder(File folder) {
        File[] files = folder.listFiles();
        if(files!=null) {
            for(File file: files) {
                if(file.isDirectory()) {
                    deleteFolder(file);
                } else {
                    file.delete();
                }
            }
        }
        folder.delete();
    }

}

其他问题

如果你报的问题不是这个,但又也是违反了OPC合规性的错误,那么你可以尝试以下方式:

解压后的docProps文件夹内有个core.xml,打开它,然后里面会有一些标签:

解决POI读取Excel出现的错误:OPC Compliance error [M4.3]: Producers shall not create a document element that co_第8张图片


 点赞,你的认可是我创作的动力 !
收藏,你的青睐是我努力的方向!
✏️评论,你的意见是我进步的财富! 

你可能感兴趣的:(Java,excel)