2010-11-12 3 views
2

Да, у меня проблема с памятью PHP. Мое предложение хозяина макс. для использования предела памяти 64 МБ, и как-то, когда я загружаю + функции обработки, превышает эту память, и im получает ошибку (не всегда, хотя, зависит от размера изображения)PHP: использование памяти и кода с низкой памятью

Когда я загружаю изображение размером около 1 мб или ниже, загружает, и вы можете обрезать и сохранить его.

Но когда я загружаю изображение размером около 2 мб или более (мой лимит на функцию загрузки составляет 6 МБ), он загружается, а затем, когда вы обрезаете изображение и хотите его сохранить, я получаю ошибку «из памяти».

Я попытался imagedestroy() после любой функции в gd, я больше не использую, но это не повлияло на нее. Хотя im только с использованием GDfunctions в случае урожая

Итак, есть ли что-нибудь, что я могу освободить из памяти при загрузке?

Или, может быть, вообще, как освободить использование памяти php?

Вот мой сценарий:

switch($action) { 

    case 'upload': 


    $userid = $USER; 
    $user = getUserInfo($userid); 
    $lasttime = $user['showURP']["photo_lasttime"]; 

    $upload_name = "file"; 
    $max_file_size_in_bytes = 8388608; 
    $extension_whitelist = array("jpg", "gif", "png", "jpeg"); 

    /* checking extensions */ 
    $path_info = pathinfo($_FILES[$upload_name]['name']); 
    $file_extension = $path_info["extension"]; 
    $is_valid_extension = false; 
    foreach ($extension_whitelist as $extension) { 
     if (strcasecmp($file_extension, $extension) == 0) { 
      $is_valid_extension = true; 
      break; 
     } 
    } 
    if (!$is_valid_extension) { 
     echo "{"; 
     echo  "error: 'Filtype not allowed!'\n"; 
     echo "}"; 
     exit(0); 
    } 
    /* checking filetype*/ 
switch(exif_imagetype($_FILES[$upload_name]['tmp_name'])) { 
    case IMAGETYPE_GIF: 
    case IMAGETYPE_JPEG: 
    case IMAGETYPE_PNG: 
     break; 
    default: 
     echo "{"; 
     echo  "error: 'This is no real image!'\n"; 
     echo "}"; 
     exit(0); 
} 

    /* file size check */ 
    $file_size = @filesize($_FILES[$upload_name]["tmp_name"]); 
    if (!$file_size || $file_size > $max_file_size_in_bytes) { 
     echo "{"; 
     echo  "error: 'Filesize exceeds the limit: 6MB'\n"; 
     echo "}"; 
     exit(0); 
    } 




    if(isset($_FILES[$upload_name])) 
     if ($_FILES[$upload_name]["error"] > 0) { 
      echo "Error: " . $_FILES["file"]["error"] . "<br />"; 
      } else { 
       $userfile = stripslashes($_FILES[$upload_name]['name']); 
       $file_size = $_FILES[$upload_name]['size']; 
       $file_temp = $_FILES[$upload_name]['tmp_name']; 
       $file_type = $_FILES[$upload_name]["type"]; 
       $file_err = $_FILES[$upload_name]['error']; 
       $file_name = $userfile; 

       if(move_uploaded_file($file_temp, "images/profilePhoto/".$file_name)) { 
        echo "{"; 
        echo  "msg: '".$file_name."'"; 
        echo "}"; 
       } 
      } 
    break; 

    case 'crop': 
    if ($_SERVER['REQUEST_METHOD'] == 'POST') { 


     $jpeg_quality = 90; 

     $src = "images/profilePhoto/".$_POST['fname']; 
     $ext= pathinfo($src, PATHINFO_EXTENSION); 


    if($ext == "jpg" OR $ext == "jpeg" OR $ext == "JPG"){ 
     $img_r = imagecreatefromjpeg($src); // <-- im getting out of memory error on this line 

    }elseif($ext == "png" OR $ext == "PNG"){ 
     $img_r = imagecreatefrompng($src); 
    }elseif($ext == "gif" OR $ext == "GIF"){ 
     $img_r = imagecreatefromgif($src); 
    } 

     if($_POST['fixed'] == 0) { 
      $targ_w = $_POST['w']; 
      $targ_h = $_POST['h']; 
     } 
     else { 
      $targ_h = $_POST['sizeh']; 
      $targ_w = $_POST['sizew']; 
     } 

     $dst_r = ImageCreateTrueColor($targ_w, $targ_h); 

     imagecopyresampled($dst_r,$img_r,0,0,$_POST['x'],$_POST['y'], 
     $targ_w,$targ_h,$_POST['w'],$_POST['h']); 
     imagedestroy($img_r); // free memory 

    $path_thumbs = "images/profilePhoto/thumbs"; 
     $filename = $USER . ".jpg"; 
     $thumb_path = $path_thumbs . '/' . $filename; 

     imagejpeg($dst_r,$thumb_path,$jpeg_quality); 
     imagedestroy($dst_r); // free memory 

     echo json_encode(array(
      'filename'=>$thumb_path 
     )); 
     unlink($src);  


    } 
    break; 
} 

Мой хозяин только поддерживает GD LIB для обрезки изображений, так что можно использовать ImageMagick косяк.

И как я уже упоминал ранее, мой хозяин имеет memory_limit на 64M, что не могу быть установлен

+0

Почему -1 ?? ... – Karem

ответ

1

Имейте в виду, что в то время как GD манипулирует изображение, оно не хранится в сжатом формате. Таким образом, объем памяти GD должен работать с изображением, прямо пропорциональным его размеру (ширина х высота), тогда как загружаемое изображение, вероятно, сжато и, следовательно, может быть намного меньше на вашем собственном диске.

Например, вы можете загрузить файл размером 1 МБ, но этот файл на самом деле имеет разрешение 1024x1024 пикселей и, следовательно, для загрузки GD потребуется примерно 4 МБ памяти, или если бы он был еще большим (скажем, 2048x2048), это было бы больше похоже на 16 МБ памяти и т. д.

+0

Привет. Спасибо, заставило меня понять! Но как я могу решить эту проблему и снизить ее использование? – Karem

+0

Я уверен, что вы пробовали «ini_set (« memory_limit »,« 1024M »);? ;-) – opHASnoNAME

+0

Да, я не могу изменить его, так как мой максимум 64M – Karem

0

Размер файла не зависит от jpeg, потому что материал сжат. Если вы работаете с этим изображением, оно хранится как растровое изображение в памяти, и я думаю, что это ваша проблема.

Вы можете попробовать ImageMagick, потому что ему не нужно столько памяти, сколько gd!

ImageMagick on php.net

+0

Мой хост не поддерживает Imagemagick – Karem

4

К сожалению, вы собираетесь быть ограничены вашей памяти предел. Библиотека GD выглядит так, как будто у нее ужасное управление памятью. Я просто попытался загрузить изображение с размерами 3951x2520 &. Использование памяти в сценариях для скриптов перешло от 512 КБ до загрузки до 50 МБ после загрузки (PHP 5.3.3, Windows 7 Home x64). Фактическое изображение должно занимать около 28,49 МБ памяти, поэтому почему GD занимает почти вдвое больше этой суммы? Понятия не имею.

Редактировать: На самом деле, похоже, причина в том, что GD хранит изображение в его внутреннем формате GD2, который не эффективен с точки зрения памяти.

Редакция 2: Похоже, что формат GD2 на самом деле раздувается примерно на 67% по сравнению с фактическим растровым изображением truecolor. Удивительно, что исходный формат GD занимает меньшую площадь, чем исходное изображение или GD2. Это я считаю из-за сглаживания, что заметно на выходе.Единственный способ, с помощью которого можно получить файл, загруженный в исходный формат GD, - сначала загрузить его, используя его функцию изображения (например, imagecreatefromjpeg), а затем сохранить его с помощью imagegd (не imagegd2), а затем перезагрузить его с помощью imagecreatefromgd. Это не очень эффективно, и сглаживание определенно происходит.

Final Edit:

Это я чувствую, это лучше, чем функция, которую я имел ранее ниже. Вы даете ему имя файла вашего файла вместе с целевой высотой & width &, оно проверит доступную память и вернет true или false, если у вас достаточно, чтобы выполнить изменение размера. Если вы предпочитаете просто знать, сколько памяти требуется, вы можете передать true как параметр $ returnRequiredMem.

function checkMemAvailbleForResize($filename, $targetX, $targetY,$returnRequiredMem = false, $gdBloat = 1.68) { 
    $maxMem = ((int) ini_get('memory_limit') * 1024) * 1024; 
    $imageSizeInfo = getimagesize($filename); 
    $srcGDBytes = ceil((($imageSizeInfo[0] * $imageSizeInfo[1]) * 3) * $gdBloat); 
    $targetGDBytes = ceil((($targetX * $targetY) * 3) * $gdBloat); 
    $totalMemRequired = $srcGDBytes + $targetGDBytes + memory_get_usage(); 
    if ($returnRequiredMem) return $srcGDBytes + $targetGDBytes; 
    if ($totalMemRequired > $maxMem) return false; 
    return true; 
} 

Примеры:

if (!checkMemAvailableForResize('path/to/file.jpg', 640,480)) die('Cannot resize!'); 

или:

$totalBytesNeeded = checkMemAvailableForResize('path/to/file.jpg',640,480,true); 

Кроме того, вы можете настроить параметр $ gdBloat в случае 68% слишком мало или слишком много накладных расходов:

checkMemAvailableForResize('path/to/file.jpg',640,480,false, 1.69); 
+0

Привет. ваш сценарий и успешно я получаю эту ошибку.Я хотел бы знать, как вы установили ограничение размеров? (сколько высот px и ширина px). Спасибо – Karem

+0

/насколько большим может быть изображение? 1024px * 1024px? – Karem

+0

Ну Например, 512x2048 равно 1048576 пикселям, но так же 1024x1024. Вы можете установить жесткий предел, если вы хотите 1024x1024, и это, вероятно, поставит вас прямо на ваш предел. чтобы быть более гибким и рассчитывать до предела вашей памяти лучше, вместо того, чтобы налагать жесткий лимит. Первая строка определяет, сколько памяти может иметь одно изображение, вы можете изменить e 32 до 24 или 48, и это уменьшит или увеличит количество MB RAM, на которое разрешено изображение. – Klinky

0

Вы должны изменить размер изображение на клиентском браузере вместо этого на сервере. Это сделано с элементом холста html5. Вы можете написать свою собственную функцию или использовать плагин. Для этого есть хороший плагин jquery.

Blueimp jQuery File Upload

Смежные вопросы