AJAX多图像上传程序在JavaScript中的进度在Firefox中不起作用

AJAX多图像上传程序在JavaScript中的进度在Firefox中不起作用,javascript,ajax,file-upload,Javascript,Ajax,File Upload,这是我的XHTML AJAX图像上传程序的完整版本,几乎可以正常工作。它使用AJAX上传文件,我不支持IE9和更高版本以及Opera11.6和更高版本(IE10和Opera12支持它)。然而,我在Firefox上遇到了麻烦 主要问题是动态地将id附加到目标(甚至将与元素[i]相关的i传递到进度事件)。它在Chrome和Opera 12中运行良好,但在Firefox 10中不起作用。事件侦听器位于下面代码的第100行 <?xml version="1.0" encoding="UTF-8"?

这是我的XHTML AJAX图像上传程序的完整版本,几乎可以正常工作。它使用AJAX上传文件,我不支持IE9和更高版本以及Opera11.6和更高版本(IE10和Opera12支持它)。然而,我在Firefox上遇到了麻烦

主要问题是动态地将id附加到目标(甚至将与
元素[i]
相关的
i
传递到进度事件)。它在Chrome和Opera 12中运行良好,但在Firefox 10中不起作用。事件侦听器位于下面代码的第100行

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en">
<head>
<title>Image Preview</title>
<script type="application/javascript">
//<![CDATA[
function images_name(s)
{
 var a = reverse(s);
 var b = a.split('.');
 var c = reverse(b[1]);
 var d = c.toLowerCase();
 var e = d.replace(/^\s+|\s+$/g,'');
 var f = e.replace(/^-+|-+$/g,'');
 var g = f.replace(/ /g,'-');
 var h = g.replace(/[--]+/g,'-');
 var i = h.replace(/[^a-zA-Z 0-9-]+/g,'');
 return i;
}


function images_preview()
{
 if (typeof FileReader=='function')
 {
  var files = document.getElementById('post_files').files;

  for (var i = 0; i < files.length; i++)
  {
   var fr = new FileReader();
   fr.file = files[i];
   fr.onloadend = function(e)
   {
    var ip = document.getElementById('images_preview');
    var file = e.target.file;

    var d1 = document.createElement('div');
    var dn = images_name(file.name);
    d1.setAttribute('id',dn);
    var t = document.createElement('img');
    t.setAttribute('alt','Preview');
    t.setAttribute('class','left');
    t.setAttribute('src',e.target.result);
    d1.appendChild(t);
    ip.appendChild(d1);

    var d2 = document.createElement('div');
    var s2 = document.createElement('span');
    var s2t = document.createTextNode(file.name);
    s2.appendChild(s2t);
    d2.appendChild(s2);
    d1.appendChild(d2);

    var d3 = document.createElement('div');
    var s3 = document.createElement('span');
    var s3t = document.createTextNode(file.type);
    s3.appendChild(s3t);
    d3.appendChild(s3);
    d1.appendChild(d3);

    var d4 = document.createElement('div');
    var s4 = document.createElement('span');
    var s4t = document.createTextNode(Math.round(file.size/1024)+' KB');
    s4.appendChild(s4t);
    d4.appendChild(s4);
    d1.appendChild(d4);

    var d5 = document.createElement('div');
    d5.setAttribute('class','progress');
    var d6 = document.createElement('div');
    d6.setAttribute('class','status');
    d5.appendChild(d6);

    d1.appendChild(d5);
   }
   fr.readAsDataURL(files[i]);
  }
 }
 else {alert('Notice: image preview not supported by your browser.');}
}


function images_upload(e)
{
 e.preventDefault();
 var n = '';

 for (var i = 0; i < document.getElementById('post_files').files.length; i++)
 {
  var file = document.getElementById('post_files').files[i];
  n = images_name(file.name);
  //alert('n1 = '+n);
  var xhr = new XMLHttpRequest();

  if (typeof xhr.upload=='object')
  {
   var upload = xhr.upload;
   upload.addEventListener('progress',function(n)
   {
    return function(e)
    {
     //alert('n = '+n);
     var loader = document.getElementById(n).getElementsByClassName('status')[0];
     var p = Math.round((e.loaded * 100) / e.total);
     loader.style.width = p+'%';
    //alert('n = ' + n);
    };

   }(n), false);
   xhr.open('POST','upload.php');
   xhr.setRequestHeader('Cache-Control','no-cache');
   xhr.setRequestHeader('X-Requested-With','XMLHttpRequest');
   xhr.setRequestHeader('X-File-Name',file.name);
   xhr.send(file);
  }
  else {var ns = true;}
 }

 if (ns) {alert('Error: your browser does not support AJAX file uploads.');}
}


function reverse(s) {return s.split('').reverse().join('');}


window.onload = function()
{
 if (window.addEventListener)
 {
  document.getElementById('form_images').addEventListener('submit',function(e) {images_upload(e);},false);
  document.getElementById('post_files').addEventListener('change',function() {images_preview();},false);
 }
}
//]]>
</script>
<style type="text/css">
.left {float: left;}
#images_preview > div {border: #000 solid 1px; clear: both; float: right; margin: 8px; overflow: auto; width: 400px;}
#images_preview > div > div {margin-top: 8px;}
#images_preview div.progress, #images_preview div.status {background-color: orange; bottom: 0px; clear: both; height: 2px; position: relative;}
#images_preview div.status {background-color: #0f0; width: 0px;}
#images_preview img {background-color: #ccc; border: #666 solid 1px; margin: 8px; max-height: 100px; max-width: 100px; padding: 4px;}
</style>
</head>

<body>

<form action="" id="form_images" method="post" enctype="multipart/form-data">
<fieldset>
<div><input id="post_files" name="post_files" multiple="multiple" size="128" type="file" /></div>
<div><input name="post_files" type="submit" /></div>

<div id="images_preview"></div>
</fieldset>
</form>

</body>
</html>

图片预览
//
.left{float:left;}
#图像_preview>div{border:#000实心1px;清除:两个;浮动:右;边距:8px;溢出:自动;宽度:400px;}
#图像_preview>div>div{margin top:8px;}
#图像预览分区进度,#图像预览分区状态{背景色:橙色;底部:0px;清除:两者;高度:2px;位置:相对;}
#图像预览分区状态{背景色:#0f0;宽度:0px;}
#图片预览图片{背景颜色:ccc;边框:666实心1px;边距:8px;最大高度:100px;最大宽度:100px;填充:4px;}
一些澄清:首先,我只关心在Firefox、Chrome、Opera 12+和IE 10+中进行这项工作,我将使用单文件非AJAX回退。但现在我只想集中精力让它发挥作用

我已经测试过了,它可以在Opera12+、IE 10、Chrome(无论什么)中使用,但甚至不能在Firefox 14(当前的夜间构建版本)中使用。我非常希望Firefox有一个合理的版本号,可以像示例中的Firefox4一样工作

没有框架,我试着提高质量,解决这样的问题可以帮助我正确地学习真正的JavaScript代码

当我发布JavaScript问题时,人们开始挑出明显应该留在示例中的东西,这是一个AJAX文件上传,所以我不明白为什么有人会删除默认值

function images_upload(e)
{
    //...
    var n = '';
    //...
    upload.addEventListener('progress',function(n)
    {
        return function(e)
        {
            //using n here
        };
    }(n), false);
以我唯一的、谦逊的、未经证实的观点:

变量
n
在第一个函数中可见(
images\u upload(e)

您将其传递给第二个函数(未命名的
函数(n)
),假设它没有被自动传递的事件对象覆盖(我对此表示怀疑),因此它在这里也是可见的(作为“不同的”
n
,请参见下面代码块中的注释):

但是,您不会将其传递给第三个函数(未命名的
函数(e)
)。网络上有很多关于此约束的帖子,但我可以想到两种解决方法(待测试,这里仅介绍精神):

更简单的是:

    upload.savemyvar=n;
    upload.addEventListener('progress',function(e)
    {
        var n=this.savemyvar;
        //using the event e and your variable n here
    }, false);
或者,我很确定它应该会起作用(尽管速度很慢):

同样,更简单的是:

    eval("upload.addEventListener('progress',function(e)
    {
        var n="+n+";
        //using the event e and your variable n here
        //don't forget to \"escape\" correctly if needed ;)
    }, false);");
在最后一种情况下,您可能需要将所有
eval
代码放在一行,这取决于JS解析器是否需要
结束代码行或仅结束
\n


请告知第一个选项是否“按原样”工作,最重要的是,它是否解决了您的问题(因为您的代码与其他浏览器配合使用听起来很奇怪)。

尝试一下,稍后会回复,谢谢您的回复!昨晚花了几个小时试图找出问题所在,并尽可能多地覆盖了基础内容……结果发现localhost存在问题,因此测试127.0.0.1和192.168.x.y以及live domains会有所不同。我目前正在为Firefox编写一份bug报告。稍后,如果有机会,我将查看我发布的代码和您发布的内容,并解决这个问题,以免让您挂起。将for循环中的所有内容封装到新函数()中{}修复了变量范围并解决了问题。我基本上接受了你第二个建议的一个稍微不同的版本。我很少使用eval…尽管你的帖子帮助我朝着正确的方向前进,即使这花了我一些时间。谢谢投票表决并接受作为答案。
    upload.savemyvar=n;
    upload.addEventListener('progress',function(e)
    {
        var n=this.savemyvar;
        //using the event e and your variable n here
    }, false);
    eval("upload.addEventListener('progress',function(e)
    {
        return function(e , n)
        {
            //using the event e and your variable n here
            //don't forget to \"escape\" correctly if needed ;)
        }(e , "+n+");
    }, false);");
    eval("upload.addEventListener('progress',function(e)
    {
        var n="+n+";
        //using the event e and your variable n here
        //don't forget to \"escape\" correctly if needed ;)
    }, false);");