galkahana / HummusJS

Node.js module for high performance creation, modification and parsing of PDF files and streams
http://www.pdfhummus.com
Other
1.15k stars 170 forks source link

Pdf file creation issue with createWriterToModify() and streams #208

Open nicdlz opened 7 years ago

nicdlz commented 7 years ago

Hi !

We have some troubles with the pdfWriter We're trying to add a comment in a pdf file, and after download it straight in the web browser, it works without adding comment.

The trouble is that is seems to be a not endded process with the streams or the pdfWriter(). You can see it if you put a breakpoint at the end of the function. (You have to check your pdf filesize while on the breakpoint).

We call that code in an express API. The file is updated once the whole process is done. it looks like there is an asynchronous treatment somewhere in the hummus functions we call.

const addComment = (newFilepathToWrite, filepathToRead) => {
    const pdfReader = hummus.createReader(filepathToRead);
    const inStream = new hummus.PDFRStreamForFile(filepathToRead);
    const outStream = new hummus.PDFWStreamForFile(newFilepathToWrite);
    let pdfWriter = hummus.createWriterToModify(
      inStream,
      outStream
    );

/****
   some code to add comment
   Behaviour is identical without it.
****/

      pdfWriter.end();
      outStream.close();
      inStream.close();
      pdfWriter = null;
}; // put breakpoint here :D   and check the filesize. 
galkahana commented 7 years ago

donnow. try separating the pdfWriter code into a function (keep the streams as parameters to it), so it "destructs". let's see if this improve matters. otherwise, let's have sample code and sample pdf.

chunyenHuang commented 7 years ago

I think you can take look at here PDFWStreamForFile, you may try with callback. I have some examples for you as well. Hope it can help.

const express = require('express');
const hummus = require('hummus');
const fs = require('fs');
const path = require('path');
const app = express();

/**
 * Basic Creation
 * https://github.com/galkahana/HummusJS/wiki/How-to-serve-dynamically-created-pdf
 */
function createPdfInStream(hummusStream) {
    const pdfWriter = hummus.createWriter(hummusStream);
    const page = pdfWriter.createPage(0, 0, 595, 842);
    const context = pdfWriter.startPageContentContext(page);
    context.drawCircle(150, 150, 50);
    pdfWriter.writePage(page);
    pdfWriter.end();
}

app.get('/create', (req, res) => {
    res.writeHead(200, { 'Content-Type': 'application/pdf' });
    const hummusStream = new hummus.PDFStreamForResponse(res);
    createPdfInStream(hummusStream);
    res.end();
});

/**
 * Basic Modification
 */
function modifyPDF(inStream, outStream, cb) {
    const pdfWriter = hummus.createWriterToModify(inStream, outStream);
    const pageModifier = new hummus.PDFPageModifier(pdfWriter, 0);
    const context = pageModifier.startContext().getContext();
    context.drawCircle(150, 150, 50);
    pageModifier.endContext().writePage();
    pdfWriter.end();
    if (inStream.close) {
        inStream.close(() => {
            console.log('in stream done')
        });
    }
    if (outStream.close) {
        outStream.close(cb);
    }
}

app.get('/modify', (req, res) => {
    res.writeHead(200, { 'Content-Type': 'application/pdf' });
    const inStream = new hummus.PDFRStreamForFile(path.join(__dirname, 'test.pdf'));
    const outStream = new hummus.PDFStreamForResponse(res);
    modifyPDF(inStream, outStream);
    res.end();
});

/**
 * Your case
 * https://github.com/galkahana/HummusJS/blob/02730266893d288ac6a88148c8f624c41519236e/PDFWStreamForFile.js
 */
const addComment = (newFilepathToWrite, filepathToRead, cb) => {
    const inStream = new hummus.PDFRStreamForFile(filepathToRead);
    const outStream = new hummus.PDFWStreamForFile(newFilepathToWrite);
    const pdfWriter = hummus.createWriterToModify(
        inStream,
        outStream
    );

    const pageModifier = new hummus.PDFPageModifier(pdfWriter, 0);
    const context = pageModifier.startContext().getContext();
    context.drawCircle(150, 150, 50);
    pageModifier.endContext().writePage();
    pdfWriter.end();

    inStream.close(() => {
        console.log('inStream done');
    });
    outStream.close(cb);
};

app.get('/addComment', (req, res) => {
    const newFilepathToWrite = path.join(__dirname, 'new.pdf');
    const filepathToRead = path.join(__dirname, 'test.pdf');
    addComment(newFilepathToWrite, filepathToRead, () => {
        // your file is ready
        console.log(fs.statSync(newFilepathToWrite).size);
        res.send('ok');
    });
    // async size = 0;
    console.log(fs.statSync(newFilepathToWrite).size);
});

app.use(express.static('./'));
app.listen(3000);
galkahana commented 7 years ago

yeah actually @chunyenHuang is right. close is async. you should provide a handler if you want to do something when it's really done.