Ошибка загрузки файла API при работе XHR - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь асинхронно загрузить файл через javascript в фоновом режиме. Я обновляю нашу библиотеку, чтобы использовать fetch вместо XHR. Запрос XHR работает правильно, и на вкладке сети отображается ожидаемый ответ, который в настоящее время представляет собой просто var_dump ($ _ FILES) и var_dump ($ _ POST).

Когда я по какой-то причине выполняю тот же вызов с fetch, PHP останавливается при создании сеанса. Я выделил это до строки:

$session = new Session;

Вот очищенная версия XHR, которая возвращает оба этих PHP массива, заполненных правильно

    var request = {},
        url = "../../lib/upload.php",
        formData = new FormData;

    formData.append(
      "PHP_SESSION_UPLOAD_PROGRESS", phpSessionKey // upload session key var
    );

    formData.append(
      "uploaded_file", this.file.baseFile // file object from an upload input
    );

    formData.append(
      "pageid", 1234
    );

    request = new XMLHttpRequest();
    request.open("POST", url, true);
    request.onreadystatechange = function () {
      if (request.readyState === 4 && request.status === 200) {
         console.log(responseText);
      }
    }
    request.send(formData);

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

    let formData = new FormData(),
        phpSessionKey = Uploader.pageid + "_" + this.file.name,
        that = this;

    formData.append(
      "PHP_SESSION_UPLOAD_PROGRESS", phpSessionKey
    );

    formData.append(
      "uploaded_file", this.file.baseFile
    );

    formData.append(
      "pageid", Uploader.pageid
    );

    fetch('../lib/upload.php', {
      method: 'POST',
      body: formData
    });

Эта выборка на вкладке сети ничего не возвращает, и, зайдя и прокомментировав затем некомментированные строки, я сузил проблему до строки создания сеанса при загрузке. php. Я, честно говоря, просто растерялся из-за того, почему это происходит в данный момент, пытаясь довести до JS стандартов до сих пор было довольно гладко.

РЕДАКТИРОВАТЬ

Вот класс сеанса в PHP:

class Session {
    private $user_id;
    private $last_login;
    private $database;
    public $user;
    public $username;

    public const MAX_LOGIN_AGE = 60 * 60 * 24; // 1 day

    // Constructor which attaches pseudo magic methods to php sessions
    public function __construct()
    {
      session_set_save_handler(
        array($this, '_open'),
        array($this, '_close'),
        array($this, '_read'),
        array($this, '_write'),
        array($this, '_destroy'),
        array($this, '_clean')
      );

      session_start();
      $this->check_stored_login();
    }

    public function _open()
    {

      if ($session_db = db_connect(DB_DEV)) {
        $this->database = $session_db;
        return true;
      }

      return false;
    }

    public function _close()
    {
      // print "Session closed.\n";

      return $this->database->close();
    }

    public function _read($id)
    {
      $id = $this->database->escape_string($id);

      // print "Session read.\n";
      // print "Sess_ID: $id\n";

      $sql = "SELECT data
              FROM sessions
              WHERE id = '{$id}'";

      if ($result = $this->database->query($sql)) {
        if ($result->num_rows) {
          $record = $result->fetch_assoc();

          return $record['data'];
        }
      }

      return '';
    }

    public function _write($id, $data)
    {
      $access = time();

      $id = $this->database->escape_string($id);
      $access = $this->database->escape_string($access);
      $data = $this->database->escape_string($data);
      // print "Session value written.\n";
      // print "Sess_ID: $id\n";
      // print "Data: $data\n\n";

      $sql = "REPLACE
              INTO sessions (`id`, `access`, `data`)
              VALUES ('{$id}', '{$access}', '{$data}')";

      $this->database->query($sql);

      return true;
    }

    public function _destroy($id)
    {
      $id = $this->database->escape_string($id);

      // print "Session destroy called.\n";

      $sql = "DELETE
              FROM sessions
              WHERE id='{$id}'";

      return $this->database->query($sql);
    }

    public function _clean($max)
    {
      $old = $time() - $max;
      $this->database->escape_string($old);

      $sql = "DELETE
              FROM sessions
              WHERE access < '{$old}'";

      return $this->database->query($sql);
    }

    public function login($user)
    {
      if ($user) {
        // prevent session fixation attacks
        session_regenerate_id();
        $this->user_id = $_SESSION['user_id'] = $user->id = $user->id;
        $this->username = $_SESSION['username'] = $user->first_name;
        $this->last_login = $_SESSION['last_login'] = time();
        $this->user = $_SESSION['user'] = $user;
        $_SESSION['search_text'] = '';
        $_SESSION['search_product_id'] = '';
        $args["last_login"] = date("Y-m-d H:m:s");
        $user->merge_attributes($args);
        $user->save();
      }
    }

    public function is_logged_in()
    {
      if (!isset($this->user_id) || !$this->last_login_recent()) {
        redirect_to(url_for('/index.php?logout'));
      }

      return true;
    }

    public function logout()
    {
      unset($_SESSION['user_id']);
      unset($_SESSION['username']);
      unset($_SESSION['last_login']);
      unset($_SESSION['user']);
      unset($this->user_id);
      unset($this->username);
      unset($this->last_login);
      unset($this->user);
      session_destroy();

      return true;
    }

    private function check_stored_login()
    {
      if (isset($_SESSION['user_id'])) {
        $this->user_id = $_SESSION['user_id'];
        $this->username = $_SESSION['username'];
        $this->last_login = $_SESSION['last_login'];
        $this->user = $_SESSION['user'];
      }
    }

    private function last_login_recent()
    {
      if (!isset($this->last_login)) {
        return false;
      } elseif ($this->last_login + self::MAX_LOGIN_AGE < time()) {
        return false;
      } else {
        return true;
      }
    }

    public function message($msg = '')
    {
      if (!empty($msg)) {
        $_SESSION['message'] = $msg;
      } else {
        return $_SESSION['message'];
      }
    }
  }
?>
...