繁体   English   中英

如何从外部脚本中止 XMLHttpRequest.upload?

[英]How to abort XMLHttpRequest.upload from the external script?

作为对为什么 $_FILES[] 总是为空的后续行动?

通过 AJAX 和 PhP 上传文件时,通常会执行以下操作(我是新手,所以请告诉我是否有更好的方法):

  • 有一个带有表格和 javascript 的文件,您可以在其中设置和发送XMLHttpRequest ,例如upload_form.php
  • 有另一个外部 php 文件来处理上传请求,例如upload.php

我的问题是这样的:

是否可以从外部 upload.php 文件中中止 XMLHttpRequest 文件? .

想要这样做的原因是,如果文件已经存在于服务器上,我想中止XMLHttpRequest ,而不是让用户等到上传完成后才知道失败。


一些图片来说明问题:

我在网络选项卡中限制了速度以夸大问题。

用户在上传目录中上传服务器上存在的文件:

成功

用户在上传目录中上传服务器上确实存在的文件:

失败

一些代码来说明问题:

upload_form.php:

<!-- enctype and method added on suggestions from previous question -->
<form class="form" id="upload_form" enctype="multipart/form-data" method="POST">
    <input type="file" name="file_to_upload" id="file_to_upload"><br>
    <input class="button" type="submit" value="Upload">
</form>

<script>
  const upload_form  = document.getElementById('upload_form');
  var file_to_upload = document.getElementById('file_to_upload');

  upload_form.addEventListener("submit", upload_file);

  function upload_file (e) {
    e.preventDefault();

    const xhr = new XMLHttpRequest()

    xhr.open("POST", "upload.php");
    xhr.upload.addEventListener("progress", e => {
      const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
      console.log(percent.toFixed(0) + "%");
    });

    // ================= MAIN PART OF QUESTION ===================
    // Can I force this to fire from upload.php if file exists?
    xhr.addEventListener("abort", e => {
      console.log(e);
    });
    // ===========================================================

    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        // update some response area here
      }
    };

    xhr.send(new FormData(upload_form));
  }
</script>

上传.php:

<?php

$target_path = "uploads/".basename($_FILES["file_to_upload"]["name"]);
$uploaded_file = $_FILES['file_to_upload']['tmp_name'];

$upload_ok = true;
$errors = [];

// ================= MAIN PART OF QUESTION ==========================
// I want this to cause the abort event to fire on the XMLHttpRequest
if (file_exists($target_path)) {
  $upload_ok = false;
  array_push($errors, 'The file already exists on the server. Please rename the file and try again.');
}
// ==================================================================

if(!$upload_ok) {
  echo 'The file was not uploaded because:<br>';
  foreach ($errors as $err) {
    echo $err.'<br>';
  }
} else {
  if(move_uploaded_file($_FILES["file_to_upload"]["tmp_name"], $target_path)) {
    echo 'File uploaded successfully';
  } else {
    echo 'Something went wrong. Please try again.';
  }
}
?>

我尝试在upload_form.php中检查readyStatestatus的不同组合,但这并没有帮助。

到 PHP 代码开始时,文件已完全上传,因此没有必要以这种方式中止它,只需返回消息即可。 相反,您可以在上传之前进行 AJAX 调用并检查文件是否存在,并且仅当文件不存在时才上传文件或向用户发送有关它的消息。

创建一个简单的exists.php ,代码如下

<?php

$target_path = "uploads/".$_GET['file'];
$file_exists = file_exists($target_path);

header('Content-Type: application/json');

// Return a JSON object with a single boolean property to indicate if the file exists
echo json_encode(['exists' => $file_exists]);

创建 promise 进行 XHR 调用并获取exists.php结果

function check_file_exists() {
  return new Promise((resolve, reject) => {
    const xhr = new XMLHttpRequest();

    xhr.open("GET", `exists.php?file=${encodeURIComponent(file_to_upload.files[0].name)}`);
    xhr.responseType = 'json';
    xhr.onreadystatechange = function() {
      if (this.readyState == 4 && this.status == 200) {
        resolve(this.response && this.response.exists);
      }
    };

    xhr.send();
  });
}

重构upload_file提交function首先调用check_file_exists promise

// An element to display a message to the user
const message = document.getElementById('message');

function upload_file(e) {
  e.preventDefault();

  message.textContent = '';

  // Call the promise to check if the selected file exists on the server
  check_file_exists().then(exists => {
    if(exists) {
      // If it exists message the user about it and do nothing else
      message.textContent = `File "${file_to_upload.files[0].name} already exists`;
    } else {
      // If it does not exists upload the file
      const xhr = new XMLHttpRequest();

      xhr.open("POST", "upload.php");
      xhr.upload.addEventListener("progress", e => {
        const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0;
        console.log(percent.toFixed(0) + "%");
      });

      xhr.onreadystatechange = function() {

        if (this.readyState == 4 && this.status == 200) {
          // update some response area here
          message.textContent = this.responseText;
        }
      };

      xhr.send(new FormData(upload_form));
    }
  });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM