Сжатие Word DOC XML с помощью архиватора
Я пытаюсь создать программу на Node.js, которая анонимизировала бы заданный путь для слова doc для более крупного проекта. Я уже разархивировал файл 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()
})
});
1 ответ
Вот потенциальное решение вашей проблемы, я проверил, и это работает для меня. Первая строка будет заменена на "XXXX...".
Основная проблема с вашим существующим кодом заключалась в создании корневого каталога "extract_doc" в файле.zip, который содержит архив документов. Это не то, что ожидает Слово. Ожидается структура документа в корне архива.
Я создал функцию 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();
}