首页 > 解决方案 > 如何从 docxtemplater.js 输出 docx 以在 jszip 中输入

问题描述

使用来自jszipdocxtemplater的示例,我正在尝试将多个 docx-Documents 添加到 zip 存档中,但我失败了。我的存档仅包含 0 字节不可读的 docx 文件。

我想我不明白如何将二进制模式的 docx 文件添加到存档中。我添加了从上面提到的示例中融合而来的相当长的示例代码。

您能告诉我如何修改 generate() 函数的输出或将文件添加到 zip 存档吗?

<html>
<body>
    <button onclick="zip_docx()">Generate document</button>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/docxtemplater/3.17.9/docxtemplater.js"></script>
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip-utils.js"></script>
<script src="jszip.min.js"></script>
<!--
Mandatory in IE 6, 7, 8 and 9.
-->
<!--[if IE]>
    <script type="text/javascript" src="https://unpkg.com/pizzip@3.0.6/dist/pizzip-utils-ie.js"></script>
<![endif]-->
<script>
function loadFile(url,callback){
    PizZipUtils.getBinaryContent(url,callback);
}
function zip_docx(){
  var zip = new JSZip();
  var file1 = generate("file1");
  var file2 = generate("file2");
  var file3 = generate("file3");
  zip.file("file1.docx", file1);
  zip.file("file2.docx", file2);
  zip.file("file3.docx", file3);

  zip.generateAsync({type:"blob"})
  .then(function(content) {
      // see FileSaver.js
      saveAs(content, "example.zip");
  });
  }
function generate() {
    loadFile("https://docxtemplater.com/tag-example.docx",function(error,content){
        if (error) { throw error };

        // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
        function replaceErrors(key, value) {
            if (value instanceof Error) {
                return Object.getOwnPropertyNames(value).reduce(function(error, key) {
                    error[key] = value[key];
                    return error;
                }, {});
            }
            return value;
        }

        function errorHandler(error) {
            console.log(JSON.stringify({error: error}, replaceErrors));

            if (error.properties && error.properties.errors instanceof Array) {
                const errorMessages = error.properties.errors.map(function (error) {
                    return error.properties.explanation;
                }).join("\n");
                console.log('errorMessages', errorMessages);
                // errorMessages is a humanly readable message looking like this :
                // 'The tag beginning with "foobar" is unopened'
            }
            throw error;
        }

        var zip = new PizZip(content);
        var doc;
        try {
            doc=new window.docxtemplater(zip);
        } catch(error) {
            // Catch compilation errors (errors caused by the compilation of the template : misplaced tags)
            errorHandler(error);
        }

        doc.setData({
            first_name: 'John',
            last_name: 'Doe',
            phone: '0652455478',
            description: 'New Website'
        });
        try {
            // render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
            doc.render();
        }
        catch (error) {
            // Catch rendering errors (errors relating to the rendering of the template : angularParser throws an error)
            errorHandler(error);
        }

        var out=doc.getZip().generate({
            type:"blob",
            mimeType: "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        }) //Output the document using Data-URI
        //saveAs(out,"output.docx")
        return out
    })
}
</script>

标签: javascriptblobjszipdocxtemplater

解决方案


在研究了 muellermarkus 的评论后,我正在咨询项目负责人,并在 github 上打开了一个 issue。那里有一个答案,我在这里复制作为参考。主要障碍是在将 docx 文件添加到存档时添加 {base64: true} 作为选项。

<html lang="en">
<body>
    <button onclick="generate()">Generate document</button>
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/docxtemplater/3.17.9/docxtemplater.js"></script>
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js"></script>
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip-utils.js"></script>

<script>
var zipDocs = new PizZip();
function loadFile(url,callback){
    PizZipUtils.getBinaryContent(url,callback);
}

function generate() {

    loadFile("https://docxtemplater.com/tag-example.docx",function(error,content){
        if (error) { throw error };

        // The error object contains additional information when logged with JSON.stringify (it contains a properties object containing all suberrors).
        function replaceErrors(key, value) {
            if (value instanceof Error) {
                return Object.getOwnPropertyNames(value).reduce(function(error, key) {
                    error[key] = value[key];
                    return error;
                }, {});
            }
            return value;
        }

        function errorHandler(error) {
            console.log(JSON.stringify({error: error}, replaceErrors));

            if (error.properties && error.properties.errors instanceof Array) {
                const errorMessages = error.properties.errors.map(function (error) {
                    return error.properties.explanation;
                }).join("\n");
                console.log('errorMessages', errorMessages);
                // errorMessages is a humanly readable message looking like this :
                // 'The tag beginning with "foobar" is unopened'
            }
            throw error;
        }
        const array = ['John','Jane']
        array.forEach(function(name){
          var zip = new PizZip(content);
          var doc;
          try {
              doc=new window.docxtemplater(zip);
          } catch(error) {
              // Catch compilation errors (errors caused by the compilation of the template : misplaced tags)
              errorHandler(error);
          }
          console.log(name);
          doc.setData({
              first_name: name,
              last_name: 'Doe',
              phone: '0652455478',
              description: 'New Website'
          });

          try {
            // render the document (replace all occurences of {first_name} by John, {last_name} by Doe, ...)
            doc.render();
          }
          catch (error) {
            // Catch rendering errors (errors relating to the rendering of the template : angularParser throws an error)
            errorHandler(error);
          }

          var out=doc.getZip().generate() //Output the document using Data-URI

          zipDocs.file(name+".docx", out, {base64: true});
          console.log(name, " wurde gezippt.");

      })
      var content = zipDocs.generate({ type: "blob" });
      // see FileSaver.js
      saveAs(content, "example.zip");
    })
}
</script>

推荐阅读