提问人:Willem-Jan Meijer 提问时间:10/3/2023 最后编辑:Willem-Jan Meijer 更新时间:10/3/2023 访问量:80
PHP echo() 损坏 readfile() 输出
PHP echo() corrupting readfile() output
问:
我有这个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 (德贝安) PHP 8.0.30 FPM/快速CGI
问题:
- 当第 65 行的 readfile() 语句被注释掉时,第 89 行的 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;
}
?>
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.";
}
?>
答:
0赞
volkerschulz
10/3/2023
#1
为了
ob_end_clean();
要工作,您需要首先使用
ob_start();
并且不得使用
ob_flush();
介于两者之间。
0赞
Willem-Jan Meijer
10/3/2023
#2
@Progman提到的话题为我指明了正确的方向。我重新编写了代码如下:
index.html:
<!DOCTYPE html>
<html>
<head>
<title>CSV to PDF</title>
</head>
<body>
<div id="downloadlink">
<a href="insuromatic.csv">Download demo CSV bestand</a>
</div>
<div id="generatePDFS"></div>
<input type="file" id="csvFileInput" name="csvFileInput"><br />
<button id="generatePDFSbutton">Genereer en download PDF bestanden</button><br />
<script src="https://code.jquery.com/jquery-3.7.1.min.js"></script>
<script>
$(document).ready(function() {
$("#generatePDFSbutton").click(function() {
// Get the selected CSV file
var csvFile = $("#csvFileInput")[0].files[0];
if (csvFile) {
// Create a FormData object to send the file data
var formData = new FormData();
formData.append('action', 'generatePDFS');
formData.append('csvFile', csvFile);
$.ajax({
url: 'generatepdf.php',
type: 'POST',
data: formData,
processData: false,
contentType: false,
success: function(response) {
$("#generatePDFS").html(response);
fetch('download.php', {
method: 'GET',
responseType: 'blob',
})
.then(response => response.blob())
.then(blob => {
const url = window.URL.createObjectURL(blob);
const a = document.createElement('a');
a.style.display = 'none';
a.href = url;
a.download = 'pdf.zip';
document.body.appendChild(a);
a.click();
window.URL.revokeObjectURL(url);
})
.catch(error => {
console.error('Error downloading file:', error);
});
}
});
} else {
alert('Please select a CSV file');
}
});
});
</script>
</body>
</html>
generatepdf.php:
<?php
if (isset($_POST['action'])) {
$action = $_POST['action'];
if ($action === 'generatePDFS') {
// Call PHP function generatePDFS
$result = generatePDFS();
echo $result;
}
}
function generatePDFS() {
// Include necessary libraries for database, PDF generation, and ZIP compression.
require_once('db_connection.php');
require_once('tcpdf/tcpdf.php');
if (isset($_POST['action'])) {
// Get uploaded file data
$csvFile = $_FILES['csvFile']['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/testomatic/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 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 "$processedRecords van de $totalRecords records verwerkt.<br />\n";
// Close the PDF document
$pdf->Close();
}
fclose($handle);
}
// Close the MySQL connection
mysqli_close($conn);
//Prevent any further execution
exit;
}
}
?>
进度将正确显示并提供下载。问题已解决。
评论