PHP echo() 损坏 readfile() 输出

问题描述 投票:0回答:1

我有这个 PHP 脚本(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);
}
?>

服务器配置:

Apache/2.4.57 (Debian) PHP 8.0.30 FPM/FastCGI

问题:

  • 当第 89 行的 readfile() 语句被注释掉时,第 65 行的 echo() 语句工作正常,我看到屏幕上回显了进度
  • 当第 65 行的 echo() 语句被注释掉时,第 89 行的 readfile() 语句工作正常,我得到了包含创建的 PDF 文件的 ZIP 下载

但是,当两条线都启用时,在进度回显到屏幕后,我在屏幕上看到很多垃圾(我认为是原始 PDF 内容)。 ZIP 不提供下载。

不幸的是,我不知道我做错了什么。我尝试了 ob_end_clean()、ob_end_flush() 等几个地方,但没有运气,垃圾不断被打印。有人能指出我正确的方向吗?

//编辑:重做版本:

<?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;
}
?>

下载.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.";
}
?>
php echo readfile
1个回答
0
投票

为了

ob_end_clean();

要工作,您需要首先使用

启动输出缓冲
ob_start();

并且不得使用

ob_flush();

介于两者之间。

© www.soinside.com 2019 - 2024. All rights reserved.