HTML5 File API使用Ajax上传多个图像

时间:2015-02-20 12:34:32

标签: javascript jquery html5 fileapi

我正在尝试使用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();
    });
});
&#13;
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;
        }
&#13;
<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>
&#13;
&#13;
&#13;

我试图搞清楚,并且知道var i的值会自动在

内发生变化

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

我不知道为什么价值在“加载”功能中发生变化。

我用Google搜索了解其他人是如何做到这一点的,最后在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()中来读取文件并在循环中调用该函数时,它应该正常工作(如下面的代码片段所示)。为什么会这样?

这里有人向我解释这两件事。 提前谢谢。

我按照示例重新安排了我的代码,该代码正常运行。 (代码在下面的代码段中。)

&#13;
&#13;
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("");
    }

}
&#13;
 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;
        }
&#13;
<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>
&#13;
&#13;
&#13;

2 个答案:

答案 0 :(得分:1)

在发布+误读之前,Haven没有看过要编辑的内容
所以对于你的问题:

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

  • 2 这是因为在您的第一个代码段中,您的file变量位于全局范围内,并在迭代期间被替换。但是,在第二个中,它与showThumbnail函数作用域相关联,然后在EventListener中传递。
    为避免调用外部函数,您需要调用file绑定函数:

来自mdnreader.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));

以下示例:

&#13;
&#13;
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();
    });
});
&#13;
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;
        }
&#13;
<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>
&#13;
&#13;
&#13;

答案 1 :(得分:0)

回答问题1:

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

回答问题2:

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

原因在于addEventListener函数,它在触发load并且具有不同范围后将与for循环异步运行。然而,循环外部的函数是永久性的,并且侦听器可以使用在该范围内声明的变量(参数file)。

但是,您可以将侦听器函数绑定到文件对象。函数的范围(this)将是文件。看到小提琴这个工作。