How to use a pdflatex child process to get a PDF as a stream in Node.js?
Asked Answered
N

3

8

Here are my files:

.
├── app.js
├── res.cls
└── res.tex

And here is the relevant contents of my app.js file:

const { spawn } = require('child_process')
const latex = spawn('pdflatex', ['res.tex'])

Running this code successfully creates a res.pdf file in the same directory. However, rather than creating a file, I would like to get the PDF as a stream and send it as a response to the browser instead. I'm trying to avoid creating any PDF files in the server, I just want to send the generated PDF as a response immediately. Is it possible to alter this code to do this?

Neelyneeoma answered 10/1, 2017 at 2:48 Comment(6)
This is going to be tricky. I tried creating a named pipe called res.pdf in the output directory. This works to the extent that pdflatex tries to write to it (without removing it), but apparently it also tries to seek in its output file, which is of course not possible in a pipe. Why not simply read the output file back in? If you do all this on an in-memory filesystem, it should be plenty fast.Fragrant
Sorry, just to clarify, I'm actually trying to prevent a file being created at all. I don't want to actually save the file, I just want it to be created and sent directly as a response without having a file created in the directory.Neelyneeoma
A typical LaTeX run creates more than one file. It will typically also drop .aux and .log files, for instance. You still haven't clarified why you want to prevent a file being created... don't fall for the XY problem :)Fragrant
You're right, sorry for not providing much information. I'm basically creating a webapp that takes user form input, creates a custom PDF from it, and then sends the PDF back to the user. Because of this, I'd rather not clog up the server with the generated PDFs. I forgot about the .aux, .log, and the other generated stuff, I'd like to avoid those as well. The only current thing I can think of is just deleting all the generated files immediately after sending the response, but this doesn't seem like great practice.Neelyneeoma
Have you tried this node.js latex-wrapper?Brachycephalic
Hey Asumus, that's what I originally was trying to use. Unfortunately, I don't think I could use it if my .tex file needs to use things like .cls files with it or font files. I could be wrong though, any help about that would be greatly appreciated.Neelyneeoma
N
1

This is a bit late, but I ended up just writing my own wrapper around latex. It lets you use fonts and .cls, and other inputs. It creates a temp directory, puts the generated PDF in there and then streams the PDF back to you. The temp directory is cleaned up afterwards.

You can check out the module here: node-latex.

Neelyneeoma answered 11/8, 2017 at 10:3 Comment(0)
F
0

The node-pdflatex has the following methods.

var util = require('util');
var path = require('path');
var fs = require('fs');
var exec = require('child_process').exec;

/*
 PDFLatex class
*/
// constructor
function PDFLatex(inputPath) {
    // default settings
    this.outputDirectory = process.cwd() + "/";
    this.inputPath = inputPath;
};

PDFLatex.prototype.outputDir = function(path) {
    this.outputDirectory = path;
    return this;
};

PDFLatex.prototype.process = function() {
    if (this.inputPath && this.inputPath.length > 0) {
        var command = "pdflatex -output-directory " + this.outputDirectory + " '" + this.inputPath + "'";
        util.puts(command);
        exec(command, function(err) {
            if (err) throw err;
        });
    }
};

Solution

Once the file is generated, we can read the file, unlink the file from the directory and send the response to the browser.

 var outputDir = '/dir/pdf/a.pdf'.
 if(fs.existsSync(outputDir)) {

    var check = fs.readFileSync(outputDir);
    fs.unlinkSync(outputDir);
    res.attachment(name+'.pdf');
    res.end(check);
 }

Hope this helps.

Faires answered 13/1, 2017 at 7:55 Comment(1)
Does this still create the PDF in my server? I'm trying to change my code to stop the PDF from actually being created in the server and just sending it as a response to the browser without it remaining in my server.Neelyneeoma
C
0

Based on the pdflatex documentation it's not able to handle streams, only files.

Corkhill answered 17/1, 2017 at 11:38 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.