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

AJAX multiple image uploader progress in JavaScript not working in Firefox

本文关键字:Firefox 不起作用 JavaScript 程序 AJAX 图像      更新时间:2023-09-26

这是我的XHTML AJAX图像上传器的完整且几乎可以工作的版本。它使用AJAX上传文件,我可以不支持IE9及更旧版本和Opera11.6及更旧版(IE10和Opera12支持它)。然而,我在使用Firefox时遇到了问题。

主要问题是动态地将id附加到目标(或者甚至传递与element[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>

一些澄清:首先,我只关心在Firefox、Chrome、Opera 12+和IE 10+中进行此项工作,我将使用单文件非AJAX回退。然而,现在我只想集中精力让它发挥作用。

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

没有框架,我努力提高质量,解决这样的问题有助于我正确地学习真正的JavaScript编码。

当我发布JavaScript问题时,人们开始挑选明显应该保留的内容,例如,这是一个AJAX文件上传,所以我无法理解为什么有人会删除preventDefault。

function images_upload(e)
{
    //...
    var n = '';
    //...
    upload.addEventListener('progress',function(n)
    {
        return function(e)
        {
            //using n here
        };
    }(n), false);

在我唯一的、谦逊的、未经证实的观点中:

您的变量n在第一个函数(images_upload(e))中可见

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

function(n){...}(n)
         1       2
//1: the unnamed function's argument, should have been called differently to avoid confusion
//2: the n that is declared inside images_upload() with a limited visibility (using 'var' keyword), and which is now passed to the unnamed function as its argument

然而,你不会把它传递给你的第三个函数(未命名的function(e))。网上有很多关于这个约束的帖子,但我能想到两个解决办法(待测试,这里只是精神):

    upload.savemyvar=n;
    upload.addEventListener('progress',function(e)
    {
        return function(e , n)
        {
            //using the event e and your variable n here
        }(e , this.savemyvar);
    }, false);

更简单的是:

    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);");

在最后一种情况下,您可能需要将所有eval代码放在一行上,这取决于JS解析器是需要;来结束代码行,还是只需要'n

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