HTML5 文件 API 使用 Ajax 上传多张图片

HTML5 File API Upload Multiple Images with Ajax

我正在尝试使用 File API 上传多张图片。我想显示图片缩略图及其名称作为标题标签。问题是我没有得到正确的图片名称作为标题标签。所有图片都显示相同的名称。 这是我的原始代码...

jQuery、CSS 和 HTML

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; i < iCount; i++)
            {
                var file = files[i];
                //Only pics
                if (file.type.match('image.*'))
                {
                    var picReader = new FileReader();

                    picReader.addEventListener("load", function (event)
                    {
                        var picFile = event.target;
                    
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + file['name'] + "'/>";
                        output.insertBefore(div, null);
                        
                    });

                    //Read the image
                    $('#clear, #result').show();
                    picReader.readAsDataURL(file);
                }
                else
                {
                    alert("You can only upload image file.");
                    $(this).val("");
                }
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});
body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

我试着弄明白了,发现 var i 的值在

中自动改变

addEventListener("load", function (event){ // value of “var i” is not the same here as the value coming from outside this function. });

我不知道为什么值在“加载”函数中发生变化。

我用谷歌搜索看看其他人是如何做的,最后在 SitePoint 上找到了这个工作示例 http://www.sitepoint.com/html5-file-drag-and-drop/ 在这个例子中,我看到了这两个我不明白的主要区别(我对编程的了解很少)。

1.他在示例中使用的 for 循环语法

for (var i = 0, f; f = files[i]; i++) {

看到他正在为 var f 赋值,而不是应用停止条件。 现在我的问题是循环如何在没有指定停止条件的情况下工作?

2。读取文件的独立功能

他做了一个单独的函数ParseFile();来读取文件。 当我尝试在没有单独的文件读取功能的情况下读取文件时,它不起作用(如我的原始代码所示)。但是当我将该代码放在一个单独的函数 showThumbnail() 中以读取文件并在循环内调用该函数时,它可以正常工作(如下面的代码片段所示)。为什么会这样?

谁给我解释一下这两件事。 提前致谢。

我按照这个例子重新安排了我的代码,它可以正常工作。 (代码在下面的片段中。)

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; f = files[i]; i++)
            {
                showThumbnail(f);
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});


function showThumbnail(file)
{
    //Only pics
    if (file.type.match('image.*'))
    {
        var picReader = new FileReader();

        picReader.addEventListener("load", function (event)
        {
            var picFile = event.target;
        
            var div = document.createElement("div");

            div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
            "title='" + file['name'] + "'/>";
            output.insertBefore(div, null);
            
        });

        //Read the image
        $('#clear, #result').show();
        picReader.readAsDataURL(file);
    }
    else
    {
        alert("You can only upload image file.");
        $(this).val("");
    }

}
 body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

发帖前没看到问题的编辑+看错了
所以对于你的问题:

  • 1 这个 for 循环正在等待 file[i] 未定义。 :
    for( var i=0, f; f=files[i]; i++).
    如果 files[x] 未定义,则循环停止(即使文件 [x+1] 已定义)

  • 2 这是因为在您的第一个片段中,您的 file 变量在全局范围内并在迭代期间被替换。然而,在第二个中,它链接到 showThumbnail 函数范围,然后传入 EventListener。
    为避免调用外部函数,您需要调用 file 绑定函数:

来自 mdn : reader.onload = (function(aImg) { return function(e) { aImg.src = e.target.result; }; })(img);

所以对你来说,

picReader.addEventListener("load", (function(aImg) { return function (event)
                    {
                        var picFile = event.target;
                        console.log(picFile);
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + aImg['name'] + "'/>";
                        output.insertBefore(div, null);

                    }; })(file));

示例如下:

var output = document.getElementById("result");

$(document).ready(function ()
{
    //Check File API support
    if (window.File && window.FileList && window.FileReader)
    {
        $('#files').on("change", function (event)
        {
            var files = event.target.files; //FileList object

            var iCount = files.length;

            for (var i = 0, f; i < iCount; i++)
            {
                var file = files[i];
                //Only pics
                if (file.type.match('image.*'))
                {
                    var picReader = new FileReader();

                    picReader.addEventListener("load", (function(aImg) { return function (event)
                    {
                        var picFile = event.target;
                        console.log(picFile);
                        var div = document.createElement("div");

                        div.innerHTML = "<img class='thumbnail' src='" + picFile.result + "'" +
                        "title='" + aImg['name'] + "'/>";
                        output.insertBefore(div, null);
                        
                    }; })(file));

                    //Read the image
                    $('#clear, #result').show();
                    picReader.readAsDataURL(file);
                }
                else
                {
                    alert("You can only upload image file.");
                    $(this).val("");
                }
            }
        });
    }
    else
    {
        console.log("Your browser does not support File API");
    }


    $("#upload").on('submit',(function()
    {
        var data = new FormData(this);

        var iUploaded = 0;
        
        setTimeout(function()
        {
            var iCount = document.getElementById('files').files.length;
            
            for (var i = 0; i < iCount ; i++)
            {
                data.append("Index", i);
                $.ajax(
                {
                    url: "upload.php",
                    type: "POST",
                    data: data,
                    contentType: false,
                    cache: false,
                    processData:false,
                    async: false,
                    success: function(response)
                    {
                        var sRes = response.split("|-|");
                        
                        if(sRes['0'] == 'success')
                        {
                            iUploaded = iUploaded + 1;
                            $("#message").html(iUploaded + " of " + sRes['1'] + " Pictures Uploaded")
                        }
                    }
                });
            }
        }, 500);
    }));
    

    $("#files").change(function()
    {
        $("#submit").trigger("click");
    });


    $('#clear').on("click", function ()
    {
        $('.thumbnail').parent().remove();
        $('#result').hide();
        $('#files').val("");
        $(this).hide();
    });
});
body{
            font-family: 'Segoe UI';
            font-size: 12pt;
        }

        header h1{
            font-size:12pt;
            color: #fff;
            background-color: #1BA1E2;
            padding: 20px;

        }
        article
        {
            width: 80%;
            margin:auto;
            margin-top:10px;
        }


        .thumbnail{

            height: 100px;
            margin: 10px;
            float: left;
        }
        #clear{
            display:none;
        }
        #result {
            border: 4px dotted #cccccc;
            display: none;
            float: left;
            margin:0 auto;
        }
        #result > div {
            float: left;
        }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<article>
    <form id="upload" onsubmit="return false">
        <label for="files">Select multiple files: </label><br /><br />
        <input id="files" name="files[]" type="file" multiple/><br /><br />
        <input type="Submit" value="submit" id="submit"></input>
        <button type="button" id="clear">Clear</button><br /><br />
    </form>

    <div id="message"></div>
    <output id="result" />
</article>

问题 1 的答案:

for 循环在每次迭代时递增 i 1。当 i 不是 files 的索引时,返回值将是未定义的,这会中断循环。

问题 2 的答案:

我创建了一个 fiddle,它展示了如何将 showThumbnail 的代码放入 for 循环中。它也解释了这个问题。

原因在addEventListener函数后面,在load被触发后会运行与for循环异步,作用域不同。然而,循环外的函数是永久的,监听器可以使用在该范围内声明的变量(参数 file)。

然而,您可以做的是将侦听器函数绑定到文件对象。函数的范围 (this) 将是文件。请参阅 fiddle 以使其工作。