php - 为什么我的 PHP 脚本在生成缩略图时会停止?
问题描述
我是 PHP 初学者,我正在尝试构建一个图库页面,该页面将为文件夹中的所有 195 个图像输出缩略图。这些图像平均每个 8 MB。这是目前的情况:
脚本文件夹中的 php.ini
allow_url_fopen = On
display_errors = On
enable_dl = Off
file_uploads = On
max_execution_time = 999
max_input_time = 999
max_input_vars = 1000
memory_limit = 999M
post_max_size = 516M
session.gc_maxlifetime = 1440
session.save_path = "/var/cpanel/php/sessions/ea-php74"
upload_max_filesize = 512M
zlib.output_compression = Off
PHP/HTML 代码
<?php
DEFINE('UPLOAD_DIR', 'sources/');
DEFINE('THUMB_DIR', 'thumbs/');
function GenerateThumbnail($src, $dest)
{
$Imagick = new Imagick($src);
$bigWidth = $Imagick->getImageWidth();
$bigHeight = $Imagick->getImageHeight();
$scalingFactor = 230 / $bigWidth;
$newheight = $bigHeight * $scalingFactor;
$Imagick->thumbnailImage(230,$newheight,true,true);
$Imagick->writeImage($dest);
$Imagick->clear();
return true;
}
// Get list of files in upload dir
$arrImageFiles = scandir(UPLOAD_DIR);
// Remove non-images
$key = array_search('.', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('..', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('.ftpquota', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('thumbs', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
?><!DOCTYPE HTML>
<html lang="fr">
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Select Image</title>
</head>
<body>
<?php
foreach($arrImageFiles as $imageFile)
{
$thumbFullPath = THUMB_DIR . "th_" . $imageFile;
$imageFullPath = UPLOAD_DIR . $imageFile;
if (! file_exists($thumbFullPath))
{
GenerateThumbnail($imageFullPath, $thumbFullPath);
}
echo "<img alt='' src='" . $thumbFullPath . "'>";
}
?>
</body>
</html>
我不知道如何解决的两个问题是:
这是我已经尝试过的:
感谢您的任何想法,我有点迷路了。
解决方案
问题肯定是超时或资源稀缺(内存或类似的东西)。本文显示 ImageMagick 导致每个图像使用 315.03 MB 内存和 47% 的 CPU 使用率。如果您循环浏览处理器中的图像,这可能会复合/泄漏foreach
。图像转换在服务器资源上可能很昂贵。这也可能是您的一个图像文件或其他一些奇怪的问题。
阿贾克斯
解决任何这些问题的方法是小批量处理这些问题。创建一个简单的 ajax/php 循环 - 为 ajax 使用一个 html.php 页面并为处理使用一个单独的文件,如下所示:
拇指显示.php
<script>
const batchSize = 5; // number of images per send
function doThumb(nextIndex) {
$.ajax({
url: "thumb-process.php",
method: "post",
data: {nextIndex: nextIndex, batchSize: batchSize},
dataType: "json"
}).done(function(response) {
if (response.thumbs) {
response.thumbs.forEach( th => $('.thumbs').append('<img alt="" src="'+th+'" />') ) ;
}
if (response.finished) alert('finished')
else {
console.log('processed batch index #' + (nextIndex-batchSize + ' - ' + nextIndex);
nextIndex += batchSize;
setTimeout(() => { doThumb(nextIndex) }, 1000);
}
}).error(function (e) {
console.error('Error happened on batch index #' + (nextIndex-batchSize + ' - ' + nextIndex, ' - details: ', e);
})
;
}
$(document).ready(() => { doThumb(0); } )
</script>
<div class='thumb-list'></div>
拇指进程.php
function GenerateThumbnail($src, $dest)
{
$Imagick = new Imagick($src);
$bigWidth = $Imagick->getImageWidth();
$bigHeight = $Imagick->getImageHeight();
$scalingFactor = 230 / $bigWidth;
$newheight = $bigHeight * $scalingFactor;
$Imagick->thumbnailImage(230,$newheight,true,true);
$Imagick->writeImage($dest);
$Imagick->clear();
return true;
}
// Get list of files in upload dir
$arrImageFiles = scandir(UPLOAD_DIR);
// Remove non-images
$key = array_search('.', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('..', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('.ftpquota', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$key = array_search('thumbs', $arrImageFiles);
if ($key !== false)
unset($arrImageFiles[$key]);
$nextIndex = $_POST['nextIndex'];
$max = min( ($nextIndex + $_POST['batchSize']), count($arrImageFiles)-1);
$thumbs = [];
while($nextIndex < $max){
$imageFile = $arrImageFiles[$nextIndex ];
$thumbFullPath = THUMB_DIR . "th_" . $imageFile;
$imageFullPath = UPLOAD_DIR . $imageFile;
if (!$imageFile) {
$output = array('finished' => 1) ;
die(json_encode($output));
}
if (! file_exists($thumbFullPath)) {
GenerateThumbnail($imageFullPath, $thumbFullPath);
}
$thumbs[]= $thumbFullPath ;
$nextIndex++;
}
$output = array('thumbs' => $thumbs);
if ($nextIndex >= count($arrImageFiles)-1) $output['finished'] = 1 ;
echo json_encode($output);
..然后坐下来看看你的控制台。如果您遇到超时或其他错误,您会看到nextIndex
它被阻塞,您可以使用该数字作为起始索引而不是 0 重新加载您的页面。
当然,您可以在 thumb-display.php 中将所有文件路径收集在一个数组中,并通过 ajax 发送每个文件路径(这样就不必每次都重新计算该路径中的所有文件),但我个人觉得发送一个数字会更好通过帖子而不是图像路径。如果您希望发送大量文件路径而不是索引#,请告诉我。
推荐阅读
- java - 如何使用 OneSignal 从静默推送通知中获取消息?
- html - 如何垂直居中元素
- sql - 为什么实体框架不在日期范围查询中使用日期索引?
- laravel - Laravel 5.5 通配符 sudomain 在实时服务器上不起作用
- python - 如何在 python 和 tkinter 中使用自定义字体?
- paypal - PayPal 支付费用始终在发件人一方
- image-processing - 在线 url 的 VOC 图像标记
- android - 使用接口的两个活动之间的通信未按预期工作
- python - 根据包含列表对列表进行排序
- scala - Scala Futures:非确定性输出