I have this PHP script (process.php):
<?php
// Include necessary libraries for database, PDF generation, and ZIP compression.
require_once('db_connection.php');
require_once('tcpdf/tcpdf.php');
if (isset($_POST['submit'])) {
// Get uploaded file data
$csvFile = $_FILES['csv_file']['tmp_name'];
// Initialize progress variables
$totalRecords = count(file($csvFile)) - 1; // Subtract 1 for the header row
$processedRecords = 0;
// Create a temporary directory to store the PDF files
$tempDir = '/var/www/html/insuromatic/temp/';
if (!file_exists($tempDir)) {
mkdir($tempDir, 0777, true);
}
// Create a ZipArchive instance
$zip = new ZipArchive();
$zipFileName = 'pdf_archive.zip';
if ($zip->open($zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
// Open and read the CSV file
if (($handle = fopen($csvFile, "r")) !== FALSE) {
// Skip the first row (header)
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// Assuming your CSV columns are in order (column1, column2, column3)
$column1 = $data[0];
$column2 = $data[1];
$column3 = $data[2];
// Insert data into the MySQL database
$sql = "INSERT INTO import_csv_data (id, name, email) VALUES ('$column1', '$column2', '$column3')";
mysqli_query($conn, $sql);
// Generate a PDF for this record
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, "ID: $column1", 0, 1);
$pdf->Cell(0, 10, "Naam: $column2", 0, 1);
$pdf->Cell(0, 10, "Email: $column3", 0, 1);
// Customize the PDF content as needed
// Save the PDF in the temporary directory
$pdfFileName = $tempDir . "record_$column1.pdf";
$pdf->Output($pdfFileName, 'F');
// Add the PDF to the ZIP archive
$zip->addFile($pdfFileName, "record_$column1.pdf");
// Delete the record from the database
$deleteSql = "DELETE FROM import_csv_data WHERE id = '$column1'";
mysqli_query($conn, $deleteSql);
// Update progress
$processedRecords++;
// Send progress to the client
// echo "Processed $processedRecords out of $totalRecords records.<br />\n"; // LINE 65
// Flush the output buffer to send data immediately to the client
ob_flush();
flush();
// Close the PDF document
$pdf->Close();
}
fclose($handle);
}
// Close the ZIP archive
$zip->close();
// Remove temporary PDF files
array_map('unlink', glob($tempDir . '*.pdf'));
rmdir($tempDir);
// Provide the ZIP archive for download
header("Content-Type: application/zip");
header("Content-Disposition: attachment; filename=\"$zipFileName\"");
ob_end_clean();
flush();
readfile($zipFileName); // LINE 89
unlink($zipFileName); // Delete the ZIP file after download
}
// Close the MySQL connection
mysqli_close($conn);
}
?>
Server config:
Apache/2.4.57 (Debian) PHP 8.0.30 FPM/FastCGI
Problem:
- The echo() statement on line 65 works fine when the readfile() statement on line 89 is commented out, I see the progress echoed on the screen
- The readfile() statement on line 89 works fine when the echo() statement on line 65 is commented out, I get a ZIP download containing the created PDF files
However, when both lines are enabled, I see a lot of garbage on the screen (the raw PDF content I think) after the progress is echoed to the screen. The ZIP is not offered for download.
Unfortunately, I have no clue about what i'm doing wrong. I tried several places of ob_end_clean(), ob_end_flush() and so on but with no luck, the garbage keeps being printed. Can someone point me in the right direction?
//Edit: reworked version:
<?php
// Include necessary libraries for database, PDF generation, and ZIP compression.
require_once('db_connection.php');
require_once('tcpdf/tcpdf.php');
if (isset($_POST['submit'])) {
// Get uploaded file data
$csvFile = $_FILES['csv_file']['tmp_name'];
// Initialize progress variables
$totalRecords = count(file($csvFile)) - 1; // Subtract 1 for the header row
$processedRecords = 0;
// Create a temporary directory to store the PDF files
$tempDir = '/var/www/html/insuromatic/temp/';
if (!file_exists($tempDir)) {
mkdir($tempDir, 0777, true);
}
// Open and read the CSV file
if (($handle = fopen($csvFile, "r")) !== FALSE) {
// Skip the first row (header)
fgetcsv($handle);
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// Assuming your CSV columns are in order (column1, column2, column3)
$column1 = $data[0];
$column2 = $data[1];
$column3 = $data[2];
// Insert data into the MySQL database
$sql = "INSERT INTO import_csv_data (id, name, email) VALUES ('$column1', '$column2', '$column3')";
mysqli_query($conn, $sql);
// Generate a PDF for this record
$pdf = new TCPDF(PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
$pdf->AddPage();
$pdf->SetFont('helvetica', '', 12);
$pdf->Cell(0, 10, "ID: $column1", 0, 1);
$pdf->Cell(0, 10, "Naam: $column2", 0, 1);
$pdf->Cell(0, 10, "Email: $column3", 0, 1);
// Customize the PDF content as needed
// Save the PDF in the temporary directory
$pdfFileName = $tempDir . "record_$column1.pdf";
$pdf->Output($pdfFileName, 'F');
// Delete the record from the database
$deleteSql = "DELETE FROM import_csv_data WHERE id = '$column1'";
mysqli_query($conn, $deleteSql);
// Update progress
$processedRecords++;
// Send progress to the client
echo "Processed $processedRecords out of $totalRecords records.<br />\n";
// Flush the output buffer to send data immediately to the client
ob_flush();
flush();
// Close the PDF document
$pdf->Close();
}
fclose($handle);
}
// Close the MySQL connection
mysqli_close($conn);
// Output a JavaScript script to perform the redirection
echo '<script>window.location.href = "download.php";</script>';
//Prevent any further execution
exit;
}
?>
download.php:
<?php
// Specify the directory containing your PDF files
$directory = '/var/www/html/insuromatic/temp';
// Define the name of the ZIP archive file
$zipFileName = 'pdf_archive.zip';
// Create a ZipArchive object
$zip = new ZipArchive();
// Open the ZIP archive for writing
if ($zip->open($zipFileName, ZipArchive::CREATE | ZipArchive::OVERWRITE) === true) {
// Create a recursive directory iterator to scan the directory
$iterator = new RecursiveDirectoryIterator($directory);
$files = new RecursiveIteratorIterator($iterator);
// Loop through all files in the directory
foreach ($files as $file) {
// Check if the file is a PDF
if ($file->isFile() && strtolower(pathinfo($file, PATHINFO_EXTENSION)) === 'pdf') {
// Add the PDF file to the ZIP archive with its original name
$zip->addFile($file, $file->getBasename());
}
}
// Close the ZIP archive
$zip->close();
// Remove temporary PDF files
$tempDir = '/var/www/html/insuromatic/temp/';
array_map('unlink', glob($tempDir . '*.pdf'));
rmdir($tempDir);
// Set the appropriate headers for a ZIP file download
header('Content-Type: application/zip');
header('Content-Disposition: attachment; filename="' . $zipFileName . '"');
header('Content-Length: ' . filesize($zipFileName));
// Send the ZIP file to the client's browser
readfile($zipFileName);
// Delete the ZIP file from the server (optional)
unlink($zipFileName);
exit; // Terminate the script
} else {
echo "Failed to create ZIP archive.";
}
?>