使用归档器压缩 word 文档 xml

Compress word doc xml using archiver

我正在尝试在 Node.js 中制作一个程序,该程序将匿名化大型项目的 word 文档的给定路径。我已经解压缩了 docx 文件并编辑了 document.xml 文件。我现在需要做的就是重新压缩它。

我研究过使用 Archiver,但问题是它将文件夹压缩为 .zip,因此当您尝试将其转换为 docx 时,它已损坏。

fs.readFile('./extracted_doc/word/document.xml', 'utf8', (err, data) => {
                        if (err) reject(err);
                        var name = data.indexOf('<w:t>')
                        var end = data.indexOf('<\/w:t>')
                        var result = data.replace(data.slice(name + 5, end), "XXXXXXXXXXXXXXXXXX")
                        fs.writeFile('./extracted_doc/word/document.xml', result, (err) => {
                            if (err) reject(err)
                            //zipping the file back to docx
                            var output = fs.createWriteStream('./anonymized_submission.docx')
                            var archive = archiver('zip')

                            archive.on('error', function (err) {
                                throw err;
                            })

                            archive.pipe(output)
                            archive.directory("./extracted_doc", "extracted_doc")
                            archive.finalize()
                        })
                    });

这是您的问题的潜在解决方案,我已经测试过并且对我有用。它将用 'XXXX...' 替换 first 行。

您现有代码的主要问题是它在包含文档存档的 .zip 文件中创建根目录 'extracted_doc'。这不是 Word 所期望的。它需要存档根目录中的文档结构。

我创建了 zipDirectory 函数来解决这个问题。这里的主要目标是保留存档的目录结构。

const archiver = require("archiver");
const fs = require("fs");

fs.readFile('./extracted_doc/word/document.xml', 'utf8', (err, data) => {
    if (err) reject(err);
    var name = data.indexOf('<w:t>');
    var end = data.indexOf('<\/w:t>');
    var result = data.replace(data.slice(name + 5, end), "XXXXXXXXXXXXXXXXXX")
    fs.writeFile('./extracted_doc/word/document.xml', result, (err) => {
        if (err) reject(err);
        zipDirectory('./extracted_doc/', './anonymized_submission.docx');
    })
});

function zipDirectory(inputDir, outputFile) {
    let archive = archiver('zip');
    archive.on('error', function (err) {
        throw err;
    })

    let output = fs.createWriteStream(outputFile);
    archive.pipe(output);
    /* Ok, so we don't want a root name of <input_dir>, this is our workaround. */
    archive.directory(inputDir, '../');
    archive.finalize();
}