为什么我的PHP脚本在生成缩略图时会停止?
我是一名PHP初学者,我正在尝试构建一个图库页面,该页面将输出文件夹中所有195个图像的缩略图。这些图像平均每个8MB。目前的情况如下: 脚本文件夹中的php.ini为什么我的PHP脚本在生成缩略图时会停止?,php,html,imagemagick,thumbnails,Php,Html,Imagemagick,Thumbnails,我是一名PHP初学者,我正在尝试构建一个图库页面,该页面将输出文件夹中所有195个图像的缩略图。这些图像平均每个8MB。目前的情况如下: 脚本文件夹中的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 pos
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内存,CPU占用率为47%。如果以
foreach
循环的方式在处理器中循环处理图像,则会产生复合/泄漏。在服务器资源上进行图像转换可能会很昂贵。这也可能是您的图像文件或其他一些奇怪的问题
Ajax it
解决这些问题的办法是分批处理。创建一个简单的ajax/php循环-使用一个html.php页面进行ajax,并使用一个单独的文件进行处理,如下所示:
thumb display.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>
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);
常量batchSize=5;//每次发送的图像数
函数doThumb(nextIndex){
$.ajax({
url:“thumb process.php”,
方法:“张贴”,
数据:{nextIndex:nextIndex,batchSize:batchSize},
数据类型:“json”
}).完成(功能(响应){
if(response.thumbs){
response.thumbs.forEach(th=>$('.thumbs').append('');
}
if(response.finished)警报(‘finished’)
否则{
log('processed batch index#'+(nextIndex batchSize+'-'+nextIndex);
nextIndex+=批量大小;
setTimeout(()=>{doThumb(nextIndex)},1000);
}
}).错误(函数(e){
console.error('批索引#'+(nextIndex batchSize+'-'+nextIndex'-详细信息:',e)上发生错误);
})
;
}
$(document).ready(()=>{doThumb(0);})
thumb process.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>
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);
函数GenerateThumbnail($src,$dest)
{
$Imagick=新Imagick($src);
$bigWidth=$Imagick->getImageWidth();
$bighight=$Imagick->getImageHeight();
$scalingFactor=230/$bigWidth;
$newheight=$bighight*$scalingFactor;
$Imagick->thumbnailImage(230,$newheight,true,true);
$Imagick->writeImage($dest);
$Imagick->clear();
返回true;
}
//获取上载目录中的文件列表
$arrImageFiles=scandir(上传目录);
//删除非图像
$key=array_search('.',$arrImageFiles);
如果($key!==false)
取消设置($arrImageFiles[$key]);
$key=array_search(“..”,$arrImageFiles);
如果($key!==false)
取消设置($arrImageFiles[$key]);
$key=array_search('.ftpquota',$arrImageFiles);
如果($key!==false)
取消设置($arrImageFiles[$key]);
$key=array_search('thumbs',$arrImageFiles);
如果($key!==false)
取消设置($arrImageFiles[$key]);
$nextIndex=$\u POST['nextIndex'];
$max=min($nextIndex+$_POST['batchSize']),count($arrImageFiles)-1;
$thumbs=[];
而($nextIndex<$max){
$imageFile=$ARRIGEFILES[$nextIndex];
$thumbFullPath=THUMB_DIR.“th_u”。$imageFile;
$imageFullPath=UPLOAD_DIR.$imageFile;
如果(!$imageFile){
$output=array('finished'=>1);
die(json_编码($output));
}
如果(!file_存在($thumbFullPath)){
生成缩略图($imageFullPath,$thumbFullPath);
}
$thumbs[]=$thumbFullPath;
$nextIndex++;
}
$output=array('thumbs'=>$thumbs);
如果($nextIndex>=count($arrImageFiles)-1)$output['finished']=1;
echo json_编码($output);
..然后坐下来观察你的控制台。如果你遇到超时或其他错误,你会看到nextIndex
它被阻塞了,你可以用这个数字作为起始索引而不是0重新加载你的页面
当然,您可以在thumb-display.php中收集数组中的所有文件路径,并通过ajax发送每个文件路径(这样就不必每次重新计算该路径中的所有文件),但就我个人而言,通过post而不是图像路径发送数字会让我感觉更好。请告诉我您是否希望发送大量文件路径而不是索引。@kinglish的答案是通过ajax加载它们很好,但我认为这不是正确的方法。这会减轻服务器的一些处理,因为它不运行它们但如果你想让很多用户访问195张图片,这仍然不是一个好的解决方案 这里最大的问题是,您正试图根据请求处理图像,因此每次页面加载都会请求并重新创建所有195个图像。这对性能不好,而且您网站上的10个用户可能会通过刷新页面几次而使服务器崩溃,除非您为此支付的费用超过10美元/月 所以,这里有一个更好的解决方案 仅在198个图像的循环上运行图像处理脚本服务器端。 您可以查看如何运行命令来执行php文件,或者如果您使用SSH连接到linux机器中,只需执行“php yourfile.php” 脚本运行和处理图像的速度将比通过浏览器请求时快。[不知道细节,只是它是这样工作的] 将图像存储到“缩略图”目录中,然后像通常通过标签一样加载它们。 TADA的问题解决了。这样你只处理一次,剩下的时间你只为他们服务