![](/img/trans.png)
[英]Attaching onprogress listener to XMLHttpRequest.upload stops POST data from being sent (wtf?)
[英]How to abort XMLHttpRequest.upload from the external script?
通过 AJAX 和 PhP 上传文件时,通常会执行以下操作(我是新手,所以请告诉我是否有更好的方法):
XMLHttpRequest
,例如upload_form.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中检查readyState
和status
的不同组合,但这并没有帮助。
到 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]);
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.