Попытка загрузить несколько изображений, используя XHR 2 и PHP - PullRequest
1 голос
/ 12 марта 2012

У меня возникают проблемы при попытке загрузить файлы, используя последнюю версию 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-человек, я не уверен на 100%).

Любая помощь будет принята с благодарностью.

С уважением,Mark

1 Ответ

4 голосов
/ 12 марта 2012

Основная проблема заключалась в том, как я добавлял объект файла изображения в объект 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);
}
...