вторник, 15 июня 2010 г.

Помещаем и извлекаем данные из PDF

Разобрался как работать с аттачами в PDF через PoDoFo (кстати он недавно обновился до 0.8.1).
Смысл в следующем - создается страница и к ней прикрепляется аннотация размером 0 на 0. Таких аннотаций на страницу может быть много. В качестве аннотации может быть текст, картинка или вложенный файл. Вот этим и воспользуемся.
Итак - сама страница будет отображать данные в красивом виде, таблички там и прочее. Это нам неинтересно на данном этапе. Сейчас важно научиться создавать вложенные файлы.

Вот пример кода, который поместит все файлы из некого каталога в аннотацию к первой странице PDF.
{
  PdfMemDocument document;
 
  //создаем страницу
  PdfPage* pPage = document.CreatePage( PdfPage::CreateStandardPageSize( ePdfPageSize_A4 ) );
 
  //визуальное отображение страницы
  PdfPainter painter;
  painter.SetPage( pPage );
  PdfFont * pFont = document.CreateFont( "Arial" );
  pFont->SetFontSize( 18.0 );
  painter.SetFont( pFont );
  painter.DrawText( 56.69, pPage->GetPageSize().GetHeight() - 56.69, "PDF PAGE");
  painter.FinishPage();
 
  QDir dr("E:\\DIR");
  dr.setFilter(QDir::Files);
  QStringList lst = dr.entryList();
 
  foreach (QString file, lst)
  {
   QString filename = dr.absolutePath() + "/" + file;
   PdfAnnotation * pAnn = pPage->CreateAnnotation(ePdfAnnotation_FileAttachement,
     PdfRect());

   PdfFileSpec filespec(filename.toStdString().c_str(), true, &document);
   pAnn->SetFileAttachement(filespec);

  }
  document.Write("test.pdf");
}

* This source code was highlighted with Source Code Highlighter.
Более сложным было понять как извлечь аттачи. Документаци на этот счет крайне скудна, пришлось разбираться по исходному коду и изучать спецификацию по PDF от Adobe.
Вот код, который извлекает все аттачи и складывает их в папку.
{
  PdfMemDocument doc(
"test.pdf");
  PdfVecObjects vec = doc.GetObjects();
  PdfPage* page = doc.GetPage(0);
 
int numann = page->GetNumAnnots();
  QString dirname =
"e:/OUT/";
 
for (int i = 0; i < numann; i++)
  {
   PdfAnnotation * pAnn = page->GetAnnotation(i);
   
if (pAnn->HasFileAttachement())
   {
     PdfFileSpec * attach = pAnn->GetFileAttachement();
     QString filename(attach->GetFilename().GetString());
    
int li = filename.lastIndexOf("/");
     filename = filename.mid(li + 1);

     PdfObject * obj = attach->GetObject();

     PdfDictionary pob = obj->GetDictionary().GetKey(
"EF")->GetDictionary();
     PdfReference
ref = pob.GetKey("F")->GetReference();
     PdfObject * obstream = vec.GetObject(
ref);
    
    
if (obstream->HasStream())
     {
      PdfStream * stream = obstream->GetStream();
      
char*  pDecoded;
      pdf_long lDecoded;
      stream->GetFilteredCopy(&pDecoded, &lDecoded);
    
      PdfFileOutputStream
out(QString(dirname + filename).toStdString().c_str());
      
out.Write(pDecoded, lDecoded);
      
out.Close();
     }
   }
  }
}


* This source code was highlighted with Source Code Highlighter.

1 комментарий:

  1. Отличная статья!
    А как средствами PoDoFo сделать в Qt простой viewer pdf-файлов?

    ОтветитьУдалить