我在尝试使用最新的XHR 2和PHP上传文件时遇到了问题。
我的代码如下:
HTML ...
<!doctype html>
<html>
<head>
<title>XHR Multiple File Upload</title>
<link rel="stylesheet" type="text/css" href="upload.css">
</head>
<body>
<input type="file" id="upload" multiple="true" accept="image/*">
<a href="#" id="upload-link">Click here to upload multiple files</a>
<script src="upload.js"></script>
</body>
</html>
的JavaScript
var formdata, link, input, doc = document;
if (window.FormData) {
formdata = new FormData();
}
function init(){
link = doc.getElementById("upload-link"),
input = doc.getElementById("upload");
link.addEventListener("click", process, false);
input.addEventListener("change", displaySelectedFiles, false);
}
function process (e) {
// If the input element is found then trigger the click event (which opens the file select dialog window)
if (input) {
input.click();
}
e.preventDefault();
}
function displaySelectedFiles(){
// Once a user selects some files the 'change' event is triggered (along with this listener function)
// We can access selected files via 'this.files' property object.
var files = this.files,
count = 0,
len = files.length;
while (count < len) {
createImage(files[count]);
count++;
}
var confirm = doc.createElement("input");
confirm.type = "submit";
confirm.value = "Upload these files";
confirm.id = "confirm";
doc.body.appendChild(confirm);
confirm.addEventListener("click", uploadFiles, false);
}
function createImage (file) {
var element = doc.createElement("img");
element.file = file;
element.classList.add("thumbnail");
// We store the file object as a property of the image (for use later)
doc.body.appendChild(element);
// The FileReader object lets web applications asynchronously read the contents of files
var reader = new FileReader();
reader.onload = (function (img) {
return function (e) {
img.src = e.target.result;
};
})(element);
reader.readAsDataURL(file);
}
function uploadFiles(){
var reader = new FileReader(),
imgs = doc.querySelectorAll(".thumbnail"),
count = 0,
len = imgs.length;
while (count < len) {
// Once image file is read then we can 'send' the upload request
reader.onload = function (e) {
formdata.append("images[]", e.target.result);
}
reader.readAsDataURL(imgs[count].file);
count++;
}
fileUpload();
}
function fileUpload(){
var xhr = new XMLHttpRequest();
function progressListener (e) {
console.log("progressListener: ", e);
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
console.log("Percentage loaded: ", percentage);
}
};
function finishUpload (e) {
console.log("Finished Percentage loaded: 100");
};
// XHR2 has an upload property with a 'progress' event
xhr.upload.addEventListener("progress", progressListener, false);
// XHR2 has an upload property with a 'load' event
xhr.upload.addEventListener("load", finishUpload, false);
// Begin uploading of file
xhr.open("POST", "upload.php");
xhr.onreadystatechange = function(){
console.info("readyState: ", this.readyState);
if (this.readyState == 4) {
if ((this.status >= 200 && this.status <= 200) || this.status == 304) {
if (this.responseText != "") {
console.warn(xhr.responseText);
}
}
}
};
xhr.send(formdata);
}
window.addEventListener("DOMContentLoaded", init, false);
PHP(我不确定PHP代码并通过本文http://net.tutsplus.com/tutorials/javascript-ajax/uploading-files-with-ajax/找到了以下内容)
foreach ($_FILES["images"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$name = $_FILES["images"]["name"][$key];
move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploaded-images/" . $_FILES['images']['name'][$key]);
}
}
echo "Successfully Uploaded Images";
我收到成功消息,但没有文件上传到相关文件夹。我认为formdata
没有通过JavaScript正确存储,或者它没有被正确地传递给服务器以供PHP访问(或者它可能是我从上面链接到的那篇文章抓取的PHP代码不起作用 - 因为我不是一个PHP人,我不是百分百肯定的。)
非常感谢任何帮助。
亲切的问候, 标记
答案 0 :(得分:4)
主要问题是我如何将图像文件对象附加到FormData对象。
代码的工作版本可以在下面找到,也可以在GitHub上找到:https://github.com/Integralist/XHR2-Multiple-File-Upload--with-PHP-
<强> HTML 强>
<!doctype html>
<html>
<head>
<title>XHR Multiple File Upload</title>
<link rel="stylesheet" type="text/css" href="upload.css">
</head>
<body>
<!-- the file input is hidden by CSS-->
<input type="file" name="images" id="upload" multiple="true" accept="image/*">
<a href="#" id="upload-link">Click here to upload multiple files</a>
<div id="browsers">
<p>As of March 2012 the following browsers support the required features to run this demo:</p>
<ul>
<li><a href="#">Firefox 4+ (current version 10)</a></li>
<li><a href="#">Google Chrome 7+ (current version 17)</a></li>
</ul>
</div>
<script src="upload.js"></script>
</body>
</html>
<强> PHP 强>
$response = "";
foreach ($_FILES["images"]["error"] as $key => $error) {
if ($error == UPLOAD_ERR_OK) {
$name = $_FILES["images"]["name"][$key];
move_uploaded_file( $_FILES["images"]["tmp_name"][$key], "uploaded-images/" . $_FILES['images']['name'][$key]);
$response = "Files have been uploaded";
} else {
$response = $error;
}
}
echo $response;
/*
Example of formdata passed through…
array(5) {
["name"]=> array(4) {
[0]=> string(13) "Generic-2.jpg"
[1]=> string(13) "Generic-3.jpg"
[2]=> string(13) "Generic-4.jpg"
[3]=> string(13) "Generic-5.jpg"
}
["type"]=> array(4) {
[0]=> string(10) "image/jpeg"
[1]=> string(10) "image/jpeg"
[2]=> string(10) "image/jpeg"
[3]=> string(10) "image/jpeg"
}
["tmp_name"]=> array(4) {
[0]=> string(36) "/Applications/MAMP/tmp/php/phprzscxs"
[1]=> string(36) "/Applications/MAMP/tmp/php/php1cnfqk"
[2]=> string(36) "/Applications/MAMP/tmp/php/phpVkS89p"
[3]=> string(36) "/Applications/MAMP/tmp/php/phptSfmwt"
}
["error"]=> array(4) {
[0]=> int(0)
[1]=> int(0)
[2]=> int(0)
[3]=> int(0)
}
["size"]=> array(4) {
[0]=> int(130120)
[1]=> int(397627)
[2]=> int(578842)
[3]=> int(840531)
}
}
*/
<强>的JavaScript 强>
/*
* Required features:
* addEventListener (Google Chrome 1+, FF 1+, IE 9+, Opera 7+, Safari 1+)
* FileReader (Google Chrome 7+, FF 3.6+, IE 10+)
* FormData (Google Chrome 7+, FF 4+, Safari 5+)
*/
if (("addEventListener" in window) && ("FileReader" in window) && ("FormData" in window)) {
window.addEventListener("DOMContentLoaded", init, false);
} else {
alert("This demo wont work for you, sorry - please upgrade your web browser");
document.getElementById("browsers").style.display = "block";
}
var formdata, link, input, doc = document;
function init(){
formdata = new FormData()
link = doc.getElementById("upload-link"),
input = doc.getElementById("upload");
// Now we know the browser supports the required features we can display the 'browse' button
link.style.display = "inline";
link.addEventListener("click", process, false);
input.addEventListener("change", displaySelectedFiles, false);
}
function process (e) {
// If the input element is found then trigger the click event (which opens the file select dialog window)
if (input) {
input.click();
}
e.preventDefault();
}
function displaySelectedFiles(){
// Once a user selects some files the 'change' event is triggered (and this listener function is executed)
// We can access selected files via 'this.files' property object.
var img, reader, file;
for (var i = 0, len = this.files.length; i < len; i++) {
file = this.files[i];
if (!!file.type.match(/image.*/)) {
if (window.FileReader) {
reader = new FileReader();
reader.onloadend = function (e) {
createImage(e.target.result, e);
};
reader.readAsDataURL(file);
}
if (formdata) {
/*
The append method simply takes a key and a value.
In our case, our key is images[];
By adding the square-brackets to the end, we make sure each time we append another value,
we’re actually appending it to that array, instead of overwriting the image property.
*/
formdata.append("images[]", file);
}
}
}
// We only need to create the 'upload' button once
if (!doc.getElementById("confirm")) {
var confirm = doc.createElement("input");
confirm.type = "submit";
confirm.value = "Upload these files";
confirm.id = "confirm";
doc.body.appendChild(confirm);
confirm.addEventListener("click", uploadFiles, false);
}
// We only need to create the 'clear' button once
if (!doc.getElementById("clear")) {
var clear = doc.createElement("input");
clear.type = "button";
clear.value = "Clear these files";
clear.id = "clear";
doc.body.appendChild(clear);
clear.addEventListener("click", function(){
window.location.reload();
}, false);
}
}
function createImage (source, fileobj) {
var element = doc.createElement("img");
element.file = fileobj;
element.className = "thumbnail";
element.src = source;
// We store the file object as a property of the image (for use later)
doc.body.appendChild(element);
}
function uploadFiles(){
var xhr = new XMLHttpRequest();
function progressListener (e) {
console.log("progressListener: ", e);
if (e.lengthComputable) {
var percentage = Math.round((e.loaded * 100) / e.total);
console.log("Percentage loaded: ", percentage);
}
};
function finishUpload (e) {
console.log("Finished Percentage loaded: 100");
};
// XHR2 has an upload property with a 'progress' event
xhr.upload.addEventListener("progress", progressListener, false);
// XHR2 has an upload property with a 'load' event
xhr.upload.addEventListener("load", finishUpload, false);
// Begin uploading of file
xhr.open("POST", "upload.php");
xhr.onreadystatechange = function(){
console.info("readyState: ", this.readyState);
if (this.readyState == 4) {
if ((this.status >= 200 && this.status < 300) || this.status == 304) {
if (this.responseText != "") {
alert(xhr.responseText);
}
}
}
};
xhr.send(formdata);
}