如何從 docxtemplater.js 輸出 docx 以在 jszip 中輸入 (How can I output a docx from docxtemplater.js for input in jszip)


問題描述

如何從 docxtemplater.js 輸出 docx 以在 jszip 中輸入 (How can I output a docx from docxtemplater.js for input in jszip)

使用 jszipdocxtemplater 我正在嘗試將多個 docx 文檔添加到 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&quot;&gt;&lt;/script&gt;
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip.js&quot;&gt;&lt;/script&gt;
<script src="https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/1.3.8/FileSaver.js&quot;&gt;&lt;/script&gt;
<script src="https://unpkg.com/pizzip@3.0.6/dist/pizzip‑utils.js&quot;&gt;&lt;/script&gt;
<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&quot;&gt;&lt;/script&gt;
<![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&quot;,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 &amp;&amp; error.properties.errors instanceof Array) {
            const errorMessages = error.properties.errors.map(function (error) {
                return error.properties.explanation;
            }).join(&quot;\n&quot;);
            console.log('errorMessages', errorMessages);
            // errorMessages is a humanly readable message looking like this :
            // 'The tag beginning with &quot;foobar&quot; 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:&quot;blob&quot;,
        mimeType: &quot;application/vnd.openxmlformats‑officedocument.wordprocessingml.document&quot;,
    }) //Output the document using Data‑URI
    //saveAs(out,&quot;output.docx&quot;)
    return out
})

}
</script>
</code></pre>


參考解法

方法 1:

After researching the comment of muellermarkus, I was consulting with the leader of the project and I opened an issue on github. There is an answer there which I copy here as a reference. The main hurdle was the addition of {base64: true} as option when the docx‑file is added to the archive.

<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>

方法 2:

It worked for me (with Angular)

HTML

<input type="file" placeholder="Upload docx template" #docx>
<hr>
<button (click)="readDocxFile(docx)">Save</button>

Function on Component

readDocxFile(elm: any): void {
    const reader = new FileReader();

    if (elm.files.length === 0) {
      console.log('No files selected');
    }

    reader.readAsBinaryString(elm.files.item(0));

    reader.onerror = (event) => {
      console.log('error reading file', event);
    };

    reader.onload = (event) => {
      const content = event.target.result;
      const zip = new PizZip(content);
      this.filesService.save(zip, this.data);
    };
  }

My service

import { Injectable } from '@angular/core';

import * as JSZip from 'JSZip';
import { saveAs } from 'file‑saver';
declare const docxtemplater: any;

@Injectable({
  providedIn: 'root',
})
export class SaveFilesService {
  constructor() {}

  save(zipContent: any, data: any[]): void {
    const zip = new JSZip();

    data.forEach((val) => {
      const file = this.generate(zipContent, val);
      zip.file(`Word_${val.docNr}.docx`, file);
    });

    zip.generateAsync({ type: 'blob' }).then((content) => {
      saveAs(content, 'example.zip');
    });
  }

  generate(zip: any, val: any): any {
    const doc = new docxtemplater(zip).setData(val).render();
    const out = doc.getZip().generate({
      type: 'blob',
      mimeType:
        'application/vnd.openxmlformats‑officedocument.wordprocessingml.document',
    });

    return out;
  }
}

(by timmtimmVasile Radeanu)

參考文件

  1. How can I output a docx from docxtemplater.js for input in jszip (CC BY‑SA 2.5/3.0/4.0)

#blob #jszip #javascript #docxtemplater






相關問題

Hibernate:如何設置自定義 UserType 的值 (Hibernate: How to set the value of a custom UserType)

從數據庫中讀取 zip 存檔 (Reading zip archive from database)

從 JSON 網絡服務檢索 android 中的 byte[] (Retrieve byte[] in android from JSON webservice)

ORA-01465: 使用 BLOB 時,oracle 中的十六進制數無效 (ORA-01465: invalid hex number in oracle while using BLOB)

無法使用 fopen/fwrite/fclose (php) 在 mysql 中保存 xml 文件內容 (Can't save xml file content in mysql with fopen/fwrite/fclose (php))

將 Azure Blob 中的數據流式傳輸回客戶端 (Streaming Data from Azure Blobs Back to Client)

我希望將畫布保存為 mySql blob 字段中的 blob (I am looking to save a canvas as a blob in mySql blob field)

如何在 SQLite 中分段更新 blob? (How to update piecewise a blob in SQLite?)

YugabyteDB 中是否像 Oracle 或 Postgres 那樣支持 BLOB? (Is there support for BLOBs in YugabyteDB like in Oracle or Postgres?)

使用顫振將圖像作為blob存儲在mysql數據庫中 (Storing image's as blob in mysql database with flutter)

如何從 docxtemplater.js 輸出 docx 以在 jszip 中輸入 (How can I output a docx from docxtemplater.js for input in jszip)

不同語言的 Blob 請求 (Blob request in different language)







留言討論