extrair texto do pdf em Javascript

Gostaria de saber se é possível obter o texto dentro de um arquivo PDF usando apenas JavaScript? Se sim, alguém pode me mostrar como?

Eu sei que existem algumas bibliotecas java, c #, etc do lado do servidor, mas eu preferiria não usar um servidor. obrigado

Esta é uma questão antiga, mas como o pdf.js vem se desenvolvendo ao longo dos anos, gostaria de dar uma nova resposta. Isto é, pode ser feito localmente sem envolver qualquer servidor ou serviço externo. O novo pdf.js tem uma function: page.getTextContent (). Você pode obter o conteúdo de texto disso. Eu fiz isso com sucesso com o seguinte código.

  1. O que você recebe em cada etapa é uma promise. Você precisa codificar desta maneira:. .then( function(){...}) para prosseguir para a próxima etapa.

    1) PDFJS.getDocument( data ).then( function(pdf) {

    2) pdf.getPage(i).then( function(page){

    3) page.getTextContent().then( function(textContent){

  2. O que você finalmente consegue é um array de strings textContent.bidiTexts[] . Você concatena-os para obter o texto de uma página. As coordenadas dos blocos de texto são usadas para avaliar se a nova linha ou o espaço precisam ser inseridos. (Isso pode não ser totalmente robusto, mas do meu teste parece ok).

  3. Os dados do parâmetro de input precisam ser um URL ou dados do tipo ArrayBuffer. Eu usei a function ReadAsArrayBuffer (file) na API FileReader para obter os dados.

Espero que isto ajude.

Nota: De acordo com algum outro usuário, a biblioteca foi atualizada e causou a quebra do código. De acordo com o comentário por async5 abaixo, você precisa replace textContent.bidiTexts por textContent.items .

  function Pdf2TextClass(){ var self = this; this.complete = 0; /** * * @param data ArrayBuffer of the pdf file content * @param callbackPageDone To inform the progress each time * when a page is finished. The callback function's input parameters are: * 1) number of pages done; * 2) total number of pages in file. * @param callbackAllDone The input parameter of callback function is * the result of extracted text from pdf file. * */ this.pdfToText = function(data, callbackPageDone, callbackAllDone){ console.assert( data instanceof ArrayBuffer || typeof data == 'string' ); PDFJS.getDocument( data ).then( function(pdf) { var div = document.getElementById('viewer'); var total = pdf.numPages; callbackPageDone( 0, total ); var layers = {}; for (i = 1; i <= total; i++){ pdf.getPage(i).then( function(page){ var n = page.pageNumber; page.getTextContent().then( function(textContent){ if( null != textContent.bidiTexts ){ var page_text = ""; var last_block = null; for( var k = 0; k < textContent.bidiTexts.length; k++ ){ var block = textContent.bidiTexts[k]; if( last_block != null && last_block.str[last_block.str.length-1] != ' '){ if( block.x < last_block.x ) page_text += "\r\n"; else if ( last_block.y != block.y && ( last_block.str.match(/^(\s?[a-zA-Z])$|^(.+\s[a-zA-Z])$/) == null )) page_text += ' '; } page_text += block.str; last_block = block; } textContent != null && console.log("page " + n + " finished."); //" content: \n" + page_text); layers[n] = page_text + "\n\n"; } ++ self.complete; callbackPageDone( self.complete, total ); if (self.complete == total){ window.setTimeout(function(){ var full_text = ""; var num_pages = Object.keys(layers).length; for( var j = 1; j <= num_pages; j++) full_text += layers[j] ; callbackAllDone(full_text); }, 1000); } }); // end of page.getTextContent().then }); // end of page.then } // of for }); }; // end of pdfToText() }; // end of class 

Eu não pude fazer o exemplo do gm2008 funcionar (a estrutura de dados interna no pdf.js mudou aparentemente), então eu escrevi minha própria solução totalmente baseada em promise que não usa nenhum elemento DOM, queryselectors ou canvas, usando o pdf atualizado .js do exemplo em mozilla

Ele come um caminho de arquivo para o upload desde que eu estou usando com o node-webkit. Você precisa ter certeza de ter os cmaps baixados e apontados em algum lugar, e você precisa do pdf.js e do pdf.worker.js para que isso funcione.

  /** * Extract text from PDFs with PDF.js * Uses the demo pdf.js from https://mozilla.github.io/pdf.js/getting_started/ */ this.pdfToText = function(data) { PDFJS.workerSrc = 'js/vendor/pdf.worker.js'; PDFJS.cMapUrl = 'js/vendor/pdfjs/cmaps/'; PDFJS.cMapPacked = true; return PDFJS.getDocument(data).then(function(pdf) { var pages = []; for (var i = 0; i < pdf.numPages; i++) { pages.push(i); } return Promise.all(pages.map(function(pageNumber) { return pdf.getPage(pageNumber + 1).then(function(page) { return page.getTextContent().then(function(textContent) { return textContent.items.map(function(item) { return item.str; }).join(' '); }); }); })).then(function(pages) { return pages.join("\r\n"); }); }); } 

uso:

  self.pdfToText(files[0].path).then(function(result) { console.log("PDF done!", result); }) 

Aqui está um código JavaScript que faz o que você quer usando o Pdf.js em http://hublog.hubmed.org/archives/001948.html :

 var input = document.getElementById("input"); var processor = document.getElementById("processor"); var output = document.getElementById("output"); // listen for messages from the processor window.addEventListener("message", function(event){ if (event.source != processor.contentWindow) return; switch (event.data){ // "ready" = the processor is ready, so fetch the PDF file case "ready": var xhr = new XMLHttpRequest; xhr.open('GET', input.getAttribute("src"), true); xhr.responseType = "arraybuffer"; xhr.onload = function(event) { processor.contentWindow.postMessage(this.response, "*"); }; xhr.send(); break; // anything else = the processor has returned the text of the PDF default: output.textContent = event.data.replace(/\s+/g, " "); break; } }, true); 

… e aqui está um exemplo:

http://git.macropus.org/2011/11/pdftotext/example/

Para todas as pessoas que realmente querem usá-lo em um servidor de nó:

 /** * Created by velten on 25.04.16. */ "use strict"; let pdfUrl = "http://example.com/example.pdf"; let request = require('request'); var pdfParser = require('pdf2json'); let pdfPipe = request({url: pdfUrl, encoding:null}).pipe(pdfParser); pdfPipe.on("pdfParser_dataError", err => console.error(err) ); pdfPipe.on("pdfParser_dataReady", pdf => { //optionally: //let pdf = pdfParser.getMergedTextBlocksIfNeeded(); let count1 = 0; //get text on a particular page for (let page of pdf.formImage.Pages) { count1 += page.Texts.length; } console.log(count1); pdfParser.destroy(); }); 

É possível mas:

  • você teria que usar o servidor de qualquer maneira, não há nenhuma maneira de obter o conteúdo de um arquivo no computador do usuário sem transferi-lo para o servidor e voltar
  • Eu não acho que alguém tenha escrito tal biblioteca ainda

Então, se você tiver algum tempo livre, você pode aprender o formato pdf e escrever uma biblioteca como essa, ou pode simplesmente usar a biblioteca do lado do servidor, é claro.