2016-07-22 8 views
6

Можно ли вызвать инструменты CLI, такие как pdftotext, antiword, catdoc (скрипты для удаления текста), передающие строку вместо файла?Передача строки, хранящейся в памяти, в pdftotext, antiword, catdoc и т. Д.

В настоящее время я читаю PDF-файлы, вызывающие pdftotext с child_process.spawn. Я создаю новый процесс и сохраняю результат в новой переменной. Все работает нормально.

Я хотел бы передать binary от fs.readFile вместо самого файла:

fs.readFile('./my.pdf', (error, binary) => { 
    // Call pdftotext with child_process.spawn passing the binary. 
    let event = child_process.spawn('pdftotext', [ 
     // Args here! 
    ]); 
}); 

Как я могу сделать это?

ответ

2

Это определенно возможно, если команда может обрабатывать входной канал.

spawn возвращает объект ChildProcess, вы можете передать в него строку (или двоичную), записав ее stdin. Сначала строка должна быть converted до ReadableStream, затем вы можете написать строку stdin CLI на pipe.

createReadStream создает файл ReadableStream из файла.

В следующем примере загрузите pdf-файл и передайте содержимое на pdftotext, а затем отобразите первые несколько байтов результата.

const source = 'http://static.googleusercontent.com/media/research.google.com/en//archive/gfs-sosp2003.pdf' 
const http = require('http') 
const spawn = require('child_process').spawn 

download(source).then(pdftotext) 
.then(result => console.log(result.slice(0, 77))) 

function download(url) { 
    return new Promise(resolve => http.get(url, resolve)) 
} 

function pdftotext(binaryStream) { 
    //read input from stdin and write to stdout 
    const command = spawn('pdftotext', ['-', '-']) 
    binaryStream.pipe(command.stdin) 

    return new Promise(resolve => { 
    const result = [] 
    command.stdout.on('data', chunk => result.push(chunk.toString())) 
    command.stdout.on('end',() => resolve(result.join(''))) 
    }) 
} 

Для CLIs не имеет возможности читать из stdin, вы можете использовать named pipes.

Редактировать: добавить еще один пример с именованными трубами.

Как только именованные каналы создаются, вы можете использовать их как файлы. В следующем примере создаются временные именованные каналы для отправки ввода и получения вывода и отображения первых нескольких байтов результата.

const fs = require('fs') 
const spawn = require('child_process').spawn 

pipeCommand({ 
    name: 'wvText', 
    input: fs.createReadStream('document.doc'), 
}).then(result => console.log(result.slice(0, 77))) 

function createPipe(name) { 
    return new Promise(resolve => 
    spawn('mkfifo', [name]).on('exit',() => resolve())) 
} 

function pipeCommand({name, input}) { 
    const inpipe = 'input.pipe' 
    const outpipe = 'output.pipe' 
    return Promise.all([inpipe, outpipe].map(createPipe)).then(() => { 
    const result = [] 
    fs.createReadStream(outpipe) 
    .on('data', chunk => result.push(chunk.toString())) 
    .on('error', console.log) 

    const command = spawn(name, [inpipe, outpipe]).on('error', console.log) 
    input.pipe(fs.createWriteStream(inpipe).on('error', console.log)) 
    return new Promise(resolve => 
     command.on('exit',() => { 
     [inpipe, outpipe].forEach(name => fs.unlink(name)) 
     resolve(result.join('')) 
     })) 
    }) 
} 
+0

Hei @DarkKnight, tranks много !! Если я не спрошу много, могу ли я предоставить пример с именованными каналами? Оказывается, я использую другие скрипты, которые не поддерживают другой метод. –

+0

с просьбой *, пример * –

+0

Все инструменты, о которых вы упомянули, могут принимать 'stdin', указав' -'. В любом случае, я добавил еще один пример. – DarkKnight

 Смежные вопросы

  • Нет связанных вопросов^_^