JackShcherbakov
@JackShcherbakov

Ошибка net::ERR_ABORTED 413 (Request Entity Too Large) — как исправить?

Здравствуйте!

Пишу приложение, которое раз в 8 секунд делает фото и отсылает его на сервер, где оно сжимается и сохраняется. На сайте есть канвас, в который раз в секунду копируется "стоп кадр" с тега видео. Потом из канваса копируется изображение в src элемента img. Src выглядит как то так:

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAABQAAAALQCAYAAADPfd1WAAAgAElEQVR4Xqy9a49sS3IdtuvV5w4tGP5xIi2Tog3JEg2LlP1FgH+2ZQOcuafrZaxXRGR2n+EIcA0G53Z3Ve29MyPjsWJFxOl//D//r/f7/T7Ox+N4vV/H6fjn4/16H5fz/TidTsf79fuB1/l8Pk7n83E5Lvw5r/fzx3G7XY/T+zge98fxev7u976O1/N5nI7Hge+/nE7H+Xw53q/z8XrhOpfjer0e9/OZX/U83sf79dK1LpfjdMJ73+M6z+N8Oh+Xjyu/7+fjru/57YM/P9/v4/3W5/Hzceh7j/EdfB7//n0+HZfL5Xi9n7zP8/vM616Ok+73dfD5L++D93E+Xvz5enryX/z/fDodz9NP/Xx+8HKP40/8/Ot84ffdnzf9fPrv [И еще оооочень много символов]


То есть прямо в src записывается base64 код. Этот код отправляется POST-запросом на сервер.

Проблема в том, что если этот самый код больше мегабайта, то возникает ошибка из за слишком большого размера запроса.

На локальной машине я тестировал без всяких ошибок все работало отлично. Все работало идеально, пока я не загрузил файлы на хостинг.

На хостинге просто изменил разрешение видео, тем самый в разы уменьшив размер кода base64 и он успешно отправлял это на сервер.

Но мне хочется именно 1280 на 640 как минимум, если сделать в два раза меньше высоту и ширину видео (то есть разрешение) ошибка пропадет, но меня такой вариант не устраивает.

Сервер возвращает ошибку HTTP 413 Request Entity Too Large (Размер запроса слишком велик). Я попытался прописать эти строки в php сервер:

ini_set('upload_max_filesize', '500M');
ini_set('post_max_size', '500M');
header('Access-Control-Allow-Origin: *'); //JavaScript отправляет фото с другого домена


Вообще не помогло

Код в спойлере:
spoiler
Давайте пробежимся по коду:

Не думаю, что это особо поможет в решении, но мало ли.

JavaScript

делает снимок раз в 8 секунд и отправляет на сервер в виде кода base64

//Делаем снимки раз в 8 сек:

var user_id = 1;

var hidden_div = document.createElement("DIV");

hidden_div.innerHTML = '<video class="camera_stream"></video>\
  <canvas width="1280" height="720"></canvas>\
  <img class="photo">';

document.body.append(hidden_div);

hidden_div.hidden = true;


var constraints = { audio: false, video: { width: 1280, height: 720 } }; 
  
  // Older browsers might not implement mediaDevices at all, so we set an empty object first
if (navigator.mediaDevices === undefined) {
  navigator.mediaDevices = {};
}

// Some browsers partially implement mediaDevices. We can't just assign an object
// with getUserMedia as it would overwrite existing properties.
// Here, we will just add the getUserMedia property if it's missing.
if (navigator.mediaDevices.getUserMedia === undefined) {
  navigator.mediaDevices.getUserMedia = function(constraints) {

    // First get ahold of the legacy getUserMedia, if present
    var getUserMedia = navigator.webkitGetUserMedia || navigator.mozGetUserMedia;

    // Some browsers just don't implement it - return a rejected promise with an error
    // to keep a consistent interface
    if (!getUserMedia) {
      return Promise.reject(new Error('getUserMedia is not implemented in this browser'));
    }

    // Otherwise, wrap the call to the old navigator.getUserMedia with a Promise
    return new Promise(function(resolve, reject) {
      getUserMedia.call(navigator, constraints, resolve, reject);
    });
  }
}

navigator.mediaDevices.getUserMedia(constraints)
.then(function(stream) {
  var video = document.querySelector('video');
  // Older browsers may not have srcObject
  if ("srcObject" in video) {
    video.srcObject = stream;
  } else {
    // Avoid using this in new browsers, as it is going away.
    video.src = window.URL.createObjectURL(stream);
  }
  video.onloadedmetadata = function(e) {
    video.play();
  };
})
.catch(function(err) {
  console.log(err.name + ": " + err.message);
});

function takeSnapshot(){

    var hidden_canvas = document.querySelector('canvas'),
        video = document.querySelector('video.camera_stream'),
        image = document.querySelector('img.photo'),

        // Получаем размер видео элемента.
        width = video.videoWidth,
        height = video.videoHeight,

        // Объект для работы с canvas.
        context = hidden_canvas.getContext('2d');


    // Установка размеров canvas идентичных с video.
    hidden_canvas.width = width;
    hidden_canvas.height = height;

    // Отрисовка текущего кадра с video в canvas.
    context.drawImage(video, 0, 0, width, height);

    // Преобразование кадра в изображение dataURL.
    var imageDataURL = hidden_canvas.toDataURL('image/png');

    // Помещение изображения в элемент img.
    image.setAttribute('src', imageDataURL);

    var form_data = new FormData();

    form_data.append("user_id", user_id);
    form_data.append("base64", imageDataURL);


    // if(imageDataURL.length<200){
    //   takeSnapshot();
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   console.log("imageDataURL.length<200 - вызываем takeSnapshot");
    //   return false;
    // }

    var xhr = new XMLHttpRequest();
    xhr.open("POST", "xxxx.php");
    xhr.onload = function(e) {


      console.log(this.responseText);

    }

    xhr.send(form_data)


}

setInterval(function(){
  takeSnapshot();
}, 8000);


PHP

принимает картинку, которую отправил JavaScript в формате base64, сжимает ее и сохраняет в файл:

<?php 

header('Access-Control-Allow-Origin: *');


if(isset($_POST["base64"]) && isset($_POST["user_id"]) ){

$base64 = $_POST["base64"];
$user_id = $_POST["user_id"];

    // file_put_contents("bases.txt",  file_get_contents("bases.txt") . "\n" . $base64);


// $number = 64;

//   function generate_image_name($number)
//   {
//     $arr = array('1','2','3','4','5','6',
//                  '7','8','9','0');
//     // Генерируем пароль
//     $pass = "";
//     for($i = 0; $i < $number; $i++)
//     {
//       // Вычисляем случайный индекс массива
//       $index = rand(0, count($arr) - 1);
//       $pass .= $arr[$index];
//     }
//     return $pass;
//   }
//   
 function resize_photo($src, $type, $quality){

        switch($type){
            case 'image/jpeg': $source = imagecreatefromjpeg($src); break; //Создаём изображения по
            case 'image/png': $source = imagecreatefrompng($src); break;  //образцу загруженного  
            case 'image/gif': $source = imagecreatefromgif($src); break; //исходя из его формата
            default : return false;
        }
        imagejpeg($source, $src, $quality); //Сохраняем созданное изображение по указанному пути в формате jpg
        imagedestroy($source);//Чистим память
        echo "Фото было сжато успешно!\n";
        return true;
}

function base64_to_jpeg($base64_string, $output_file) {
    // open the output file for writing
    $ifp = fopen( $output_file, 'wb' ); 

    // split the string on commas
    // $data[ 0 ] == "data:image/png;base64"
    // $data[ 1 ] == <actual base64 string>
    $data = explode( ',', $base64_string );

    // we could add validation here with ensuring count( $data ) > 1
    fwrite( $ifp, base64_decode( $data[ 1 ] ) );

    // clean up the file resource
    fclose( $ifp ); 

    return $output_file; 
}

$src = "photos/" . date("Y-m-d h-i-s") . " - ". $user_id  .".jpeg";

base64_to_jpeg($base64, $src);

$quality = 60;

resize_photo($src,'image/png',  $quality);

echo "Фотография была успешно сохранена";
exit;
}
echo "Что то пошло не так";
?>


Заранее выражаю огромную благодарность всем, кто поможет!
  • Вопрос задан
  • 336 просмотров
Пригласить эксперта
Ответы на вопрос 2
А если попробовать так:
В JS:
...
let data = {
    user_id: "UID",
    base64: "b64"
};
let request= new XMLHttpRequest();
request.open("POST", "xxxxx.php", true);
request.setRequestHeader("Content-type", "application/json");
request.send(JSON.stringify(data));
...


В PHP:
$str_json = file_get_contents('php://input');
$jdom = json_decode($str_json);

if(!array_key_exists("base64", $jdom) || !array_key_exists("user_id", $jdom))
    die("NO BASE64/UID");

$base64 = $jdom["base64"];
$user_id = $jdom["user_id"];
...
Ответ написан
Hocopor
@Hocopor
Ищу интересную работу
Apache в .htaccess

ini_set определяет конфиг для php. У вас ошибку возвращает веб-сервер.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы
19 апр. 2024, в 05:01
999999 руб./за проект
19 апр. 2024, в 03:52
1000 руб./за проект
19 апр. 2024, в 03:01
1000 руб./за проект