2

I need to read the contents of a doc/docx file, which is uploaded by the user.

I've tried using jszip with docxtemplater, but I'm unable to read the file.

If besides the docs/docx files it could also read the txt files, that would be great.

I have a docx file like this:

Io sottoscritto/a __NOME__
nato a __CITTA_NASCITA__(__SIGLA_CITTA_NASCITA__) il __DATA_NASCITA__
residente a __RESIDENZA__   in via __VIA_RESIDENZA__    n __NUMERO_RESIDENZA__.

Can you give me a hand?

Link: https://codesandbox.io/s/lively-butterfly-ey8og?file=/src/App.js:0-2711

Code:

import React, { useState } from "react";
import { TextField } from "@material-ui/core";
import Docxtemplater from "docxtemplater";
import JSZip from "jszip";

export default function App() {
  const [state, setState] = useState({
    original: [],
    edit: [],
    arrayO: [],
    arrayE: []
  });
  const { original, edit, arrayO, arrayE } = state;

  const showFile = async (e) => {
    e.preventDefault();
    const reader = new FileReader();
    reader.onload = async ({ target: { result } }) => {
      /*const reg = /__[A-Z]+(?:_[A-Z]+)*__/gi;
      const row = result.split("\n");
      let arrayO = result.match(reg);
      setState((prev) => ({
        ...prev,
        original: row,
        edit: row,
        arrayO,
        arrayE: arrayO
      }));*/

      var zip = new JSZip();
      zip.loadAsync(result).then(function (zip) {
        var doc = new Docxtemplater().loadZip(zip);
        var text = doc.getFullText();
        console.log(text);
      });
    };
    reader.readAsText(e.target.files[0]);
  };

  const onChange = (value, label, key) => {
    console.log(value, label, key);
    console.log(
      original.map((e, k) =>
        e.includes(label)
          ? value === ""
            ? label
            : e.replace(label, value)
          : edit[k]
      )
    );
    setState((prev) => ({
      ...prev,
      edit: prev.original.map((e, k) =>
        e.includes(label)
          ? value === ""
            ? label
            : e.replace(label, value)
          : prev.edit[k]
      ),
      arrayE: prev.arrayE.map((e, k) =>
        k === key ? (value === "" ? label : value) : e
      )
    }));
  };

  console.log(state);

  return (
    <div className="App">
      <div style={{ flex: 1 }}>
        <div style={{}}>
          <input type="file" onChange={(e) => showFile(e)} />
          {arrayO.map((label, key) => (
            <div key={key} style={{ paddingTop: 5 }}>
              <TextField
                id="outlined-basic"
                label={label}
                variant="outlined"
                size={"small"}
                onChange={({ target: { value } }) =>
                  onChange(value, label, key)
                }
              />
            </div>
          ))}
        </div>
        <div>
          {edit.map((el, key) => (
            <div key={key}>{el}</div>
          ))}
        </div>
      </div>
      <div style={{ flex: 1, backgroundColor: "#4287f5" }}>
        {arrayO.map((el, key) => (
          <div key={key}>{el}</div>
        ))}
      </div>
      <div style={{ flex: 1, backgroundColor: "#f5cb42" }}>
        {arrayE.map((el, key) => (
          <div key={key}>{el}</div>
        ))}
      </div>
    </div>
  );
}
Paul
  • 3,644
  • 9
  • 47
  • 113

1 Answers1

2

I've changed the showfile function to use the result from the file reader to feed it into the PizZip instance :

const showFile = async (e) => {
  console.log('showfile', e)
  e.preventDefault();
  const reader = new FileReader();
  reader.onload = async (e) => {
    const content = e.target.result;
    var doc = new Docxtemplater(new PizZip(content), {delimiters: {start: '12op1j2po1j2poj1po', end: 'op21j4po21jp4oj1op24j'}});
    var text = doc.getFullText();
    console.log(text)
  };
  reader.readAsBinaryString(e.target.files[0]);
};

Note that I put some random string for the start and end delimiters to avoid parsing the document as a template.

edi9999
  • 19,701
  • 13
  • 88
  • 127
  • Thank you, I congratulate you on the Docxtemplater project, taking a better look at your project I changed some things. Can I contact you privately or can I ask directly on github, any advice on how I can do something? – Paul Jun 16 '21 at 19:57
  • Use github if it is an issue or question about the core, or my email (in the footer of : https://docxtemplater.com/) if it is a question about the commercial plugins – edi9999 Jun 16 '21 at 19:59
  • Can I ask you where can I find an example like the one you see here: https://docxtemplater.com/demo/#simple Which allows me to upload a template chosen by the user and then generate the document? – Paul Jun 16 '21 at 20:19
  • However, trying the file simple.docx that of the example https://docxtemplater.com/demo/#simple, removing the delimiters, so something like this: `var doc = new Docxtemplater (new PizZip (content), {});` calling `doc.getFullText ()` only returns the following line `{last_name} {first_name}` it does not return the `{description}` `{phone}` lines. – Paul Jun 16 '21 at 20:25
  • LInk: https://codesandbox.io/s/funny-snow-3fhw4?file=/src/App.js – Paul Jun 16 '21 at 20:26
  • About the getFullText, it returns only text from the main document. – edi9999 Jun 17 '21 at 08:41
  • word also has some footers/headers, those could be retrieved by doc.getFullText("word/header1.xml"); However, there can be multiple headers/footers in a word document so it can become complex. – edi9999 Jun 17 '21 at 08:42
  • For the file upload/ file download, this is something that you have to implement yourself, you can use express for example on the backend. – edi9999 Jun 17 '21 at 08:43
  • I also provide a docker image for people having access to the ENTREPRISE version, but it is a paid module : https://docxtemplater.com/docker/ – edi9999 Jun 17 '21 at 08:44