Moja koncepcja jest taka - na stronie jest 10 plików pdf. Użytkownik może wybrać kilka plików PDF, a następnie wybrać opcję scalania, aby utworzyć pojedynczy plik PDF zawierający wybrane strony. Jak mogę to zrobić za pomocą PHP?
Moja koncepcja jest taka - na stronie jest 10 plików pdf. Użytkownik może wybrać kilka plików PDF, a następnie wybrać opcję scalania, aby utworzyć pojedynczy plik PDF zawierający wybrane strony. Jak mogę to zrobić za pomocą PHP?
Odpowiedzi:
Robiłem to już wcześniej. Miałem plik PDF, który wygenerowałem za pomocą fpdf i musiałem dodać do niego zmienną liczbę plików PDF.
Miałem już więc obiekt fpdf i skonfigurowaną stronę (http://www.fpdf.org/) i użyłem fpdi do zaimportowania plików (http://www.setasign.de/products/pdf-php-solutions/ fpdi /) FDPI jest dodawane poprzez rozszerzenie klasy PDF:
class PDF extends FPDI
{
}
$pdffile = "Filename.pdf";
$pagecount = $pdf->setSourceFile($pdffile);
for($i=0; $i<$pagecount; $i++){
$pdf->AddPage();
$tplidx = $pdf->importPage($i+1, '/MediaBox');
$pdf->useTemplate($tplidx, 10, 10, 200);
}
To zasadniczo sprawia, że każdy plik PDF jest obrazem, który można umieścić w innym pliku PDF. Działał niesamowicie dobrze, do czego go potrzebowałem.
Poniżej znajduje się polecenie scalania php PDF.
$fileArray= array("name1.pdf","name2.pdf","name3.pdf","name4.pdf");
$datadir = "save_path/";
$outputName = $datadir."merged.pdf";
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=$outputName ";
//Add each pdf file to the end of the command
foreach($fileArray as $file) {
$cmd .= $file." ";
}
$result = shell_exec($cmd);
Zapomniałem linku, skąd go znalazłem, ale działa dobrze.
Uwaga: aby to działało, powinieneś mieć zainstalowany gs (na Linuksie i prawdopodobnie na Macu) lub Ghostscript (w Windows).
Proponuję PDFMerger z github.com , tak prosty jak:
include 'PDFMerger.php';
$pdf = new PDFMerger;
$pdf->addPDF('samplepdfs/one.pdf', '1, 3, 4')
->addPDF('samplepdfs/two.pdf', '1-2')
->addPDF('samplepdfs/three.pdf', 'all')
->merge('file', 'samplepdfs/TEST2.pdf'); // REPLACE 'file' WITH 'browser', 'download', 'string', or 'file' for output options
$cmd = "gs -q -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=".$new." ".implode(" ", $files);
shell_exec($cmd);
Uproszczona wersja odpowiedzi Chauhana
Zarówno przyjęta odpowiedź, jak i strona główna FDPI wydają się zawierać nieudane lub niepełne przykłady. Oto moje, które działa i jest łatwe do wdrożenia. Zgodnie z oczekiwaniami wymaga bibliotek fpdf i fpdi:
require('fpdf.php');
require('fpdi.php');
$files = ['doc1.pdf', 'doc2.pdf', 'doc3.pdf'];
$pdf = new FPDI();
// iterate over array of files and merge
foreach ($files as $file) {
$pageCount = $pdf->setSourceFile($file);
for ($i = 0; $i < $pageCount; $i++) {
$tpl = $pdf->importPage($i + 1, '/MediaBox');
$pdf->addPage();
$pdf->useTemplate($tpl);
}
}
// output the pdf as a file (http://www.fpdf.org/en/doc/output.htm)
$pdf->Output('F','merged.pdf');
Miałem podobny problem w swoim oprogramowaniu. Chcieliśmy połączyć kilka plików PDF w jeden plik PDF i przesłać go do usługi zewnętrznej. Używaliśmy rozwiązania FPDI, jak pokazano w rozwiązaniu Christa .
Jednak wejściowe pliki PDF, których używaliśmy, mogą być w wersji wyższej niż 1.7. Zdecydowaliśmy się ocenić komercyjny dodatek FPDI. Okazało się jednak, że niektóre dokumenty zeskanowane przez naszą biurową kserokopiarkę miały zniekształcone indeksy, co spowodowało awarię komercyjnego dodatku FPDI. Więc zdecydowaliśmy się użyć rozwiązania Ghostscript , jak w odpowiedzi Chauhana .
Ale potem otrzymaliśmy dziwne metadane we właściwościach wyjściowego pliku PDF.
Ostatecznie zdecydowaliśmy się połączyć dwa rozwiązania, aby pliki PDF zostały scalone i zdegradowane przez Ghostscript, ale metadane są ustalane przez FPDI. Nie wiemy jeszcze, jak by to działało z niektórymi zaawansowanymi formatowanymi plikami PDF, ale w przypadku skanów, których używamy, działa dobrze. Oto fragment naszej klasy:
class MergedPDF extends \FPDI
{
private $documentsPaths = array();
public function Render()
{
$outputFileName = tempnam(sys_get_temp_dir(), 'merged');
// merge files and save resulting file as PDF version 1.4 for FPDI compatibility
$cmd = "/usr/bin/gs -q -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile=$outputFileName";
foreach ($this->getDocumentsPaths() as $pdfpath) {
$cmd .= " $pdfpath ";
}
$result = shell_exec($cmd);
$this->SetCreator('Your Software Name');
$this->setPrintHeader(false);
$numPages = $this->setSourceFile($outputFileName);
for ($i = 1; $i <= $numPages; $i++) {
$tplIdx = $this->importPage($i);
$this->AddPage();
$this->useTemplate($tplIdx);
}
unlink($outputFileName);
$content = $this->Output(null, 'S');
return $content;
}
public function getDocumentsPaths()
{
return $this->documentsPaths;
}
public function setDocumentsPaths($documentsPaths)
{
$this->documentsPaths = $documentsPaths;
}
public function addDocumentPath($documentPath)
{
$this->documentsPaths[] = $documentPath;
}
}
Zastosowanie tej klasy jest następujące:
$pdf = new MergedPDF();
$pdf->setTitle($pdfTitle);
$pdf->addDocumentPath($absolutePath1);
$pdf->addDocumentPath($absolutePath2);
$pdf->addDocumentPath($absolutePath3);
$tempFileName = tempnam(sys_get_temp_dir(), 'merged');
$content = $pdf->Render();
file_put_contents($tempFileName, $content);
$cmd = "\"C:\\Program Files\\gs\\gs9.20\\bin\\gswin64c.exe\" -q -dNOPAUSE -dBATCH -dCompatibilityLevel=1.4 -sDEVICE=pdfwrite -sOutputFile=[....your parameters...]" ;
Próbowałem podobnego problemu i działa dobrze, spróbuj. Może obsługiwać różne orientacje między plikami PDF.
// array to hold list of PDF files to be merged
$files = array("a.pdf", "b.pdf", "c.pdf");
$pageCount = 0;
// initiate FPDI
$pdf = new FPDI();
// iterate through the files
foreach ($files AS $file) {
// get the page count
$pageCount = $pdf->setSourceFile($file);
// iterate through all pages
for ($pageNo = 1; $pageNo <= $pageCount; $pageNo++) {
// import a page
$templateId = $pdf->importPage($pageNo);
// get the size of the imported page
$size = $pdf->getTemplateSize($templateId);
// create a page (landscape or portrait depending on the imported page size)
if ($size['w'] > $size['h']) {
$pdf->AddPage('L', array($size['w'], $size['h']));
} else {
$pdf->AddPage('P', array($size['w'], $size['h']));
}
// use the imported page
$pdf->useTemplate($templateId);
$pdf->SetFont('Helvetica');
$pdf->SetXY(5, 5);
$pdf->Write(8, 'Generated by FPDI');
}
}
Undefined index: w
Stworzyłem warstwę abstrakcji nad FPDI (może pomieścić inne silniki). Opublikowałem go jako pakiet Symfony2 zależny od biblioteki i jako samą bibliotekę.
stosowanie:
public function handlePdfChanges(Document $document, array $formRawData)
{
$oldPath = $document->getUploadRootDir($this->kernel) . $document->getOldPath();
$newTmpPath = $document->getFile()->getRealPath();
switch ($formRawData['insertOptions']['insertPosition']) {
case PdfInsertType::POSITION_BEGINNING:
// prepend
$newPdf = $this->pdfManager->insert($oldPath, $newTmpPath);
break;
case PdfInsertType::POSITION_END:
// Append
$newPdf = $this->pdfManager->append($oldPath, $newTmpPath);
break;
case PdfInsertType::POSITION_PAGE:
// insert at page n: PdfA={p1; p2; p3}, PdfB={pA; pB; pC}
// insert(PdfA, PdfB, 2) will render {p1; pA; pB; pC; p2; p3}
$newPdf = $this->pdfManager->insert(
$oldPath, $newTmpPath, $formRawData['insertOptions']['pageNumber']
);
break;
case PdfInsertType::POSITION_REPLACE:
// does nothing. overrides old file.
return;
break;
}
$pageCount = $newPdf->getPageCount();
$newPdf->renderFile($mergedPdfPath = "$newTmpPath.merged");
$document->setFile(new File($mergedPdfPath, true));
return $pageCount;
}
To działało dla mnie w systemie Windows
dodaj następujący fragment do swojego kodu php, gdzie $ file1 to lokalizacja i nazwa pierwszego pliku PDF, $ file2 to lokalizacja i nazwa drugiego, a $ newfile to lokalizacja i nazwa pliku docelowego
$file1 = ' c:\\\www\\\folder1\\\folder2\\\file1.pdf';
$file2 = ' c:\\\www\\\folder1\\\folder2\\\file2.pdf';
$file3 = ' c:\\\www\\\folder1\\\folder2\\\file3.pdf';
$command = 'cmd /c C:\\\pdftk\\\bin\\\pdftk.exe '.$file1.$file2.$newfile;
$result = exec($command);
$command = "cmd /c C:\\pdftk\\bin\\pdftk.exe {$file1} {$file2} cat output {$new}";
Zwróć uwagę na dodatkowe wyjście kota . Zobacz przykłady PDFtk
Rozwiązanie myokyawhtun działało najlepiej dla mnie (używając PHP 5.4)
Nadal jednak będzie wyświetlany błąd - rozwiązałem go, korzystając z następującego rozwiązania:
Linia 269 pliku fpdf_tpl.php - zmieniono parametry funkcji na:
function Image($file, $x=null, $y=null, $w=0, $h=0, $type='', $link='',$align='', $resize=false, $dpi=300, $palign='', $ismask=false, $imgmask=false, $border=0) {
Tę samą zmianę dokonałem również w linii 898 pliku fpdf.php