使用JavaScript在后台动态上传文件

时间:2011-05-07 21:43:56

标签: javascript http file-upload

我正在尝试在后台上传文件。我无法使用任何框架,因此我必须手动完成。该页面已经包含一个表单,文件输入字段位于该表单中,因此我无法在表单中嵌入表单,因此我需要移动文件输入。

我正在使用的代码的问题是它似乎没有实际提交,我根本看不到任何网络活动。谁能在这里发现任何错误?

<form>
...
  <input id="photo-file-input" type="file"/>
  <button type="button" onClick="uploadBackground('photo-file-input');">Upload</button>
....
</form>

function uploadBackground(fileInputId)
{
    var iframe = createIframe('TEST');
    var form = createUploadForm('TEST', 'upload.php');
    var fileInput = document.getElementById(fileInputId);
    var fileInputParent = fileInput.parent;

    //move file input into generated form
    form.appendChild(fileInput);
    form.submit();

    iframe.onload = function()
    {
        alert('file was uploaded');
        //put the file input back where it was
        fileInputParent.appendChild(fileInput);

        //clean up generated elements
        iframe.parent.removeChild(iframe);
        form.parent.removeChild(form);
    }
}


function createUploadForm(target, action)
{
    var form = document.createElement('form');

    form.display = 'none';
    form.target = target;
    form.action = action;
    form.method = 'POST';
    form.enctype = 'multipart/form-data';

    return form;
}

function createIframe(name)
{
    var iframe;

    try
    {
            iframe = document.createElement('<iframe name="' + name + '">');
    }
    catch (ex)
    {
            iframe = document.createElement('iframe');
            iframe.name = name;
    }

    return iframe;
}

2 个答案:

答案 0 :(得分:3)

您无法复制文件输入元素并设置/保留其值。这是出于安全原因。您没有理由需要创建新表单。只需将iframe附加到页面,将表单的目标设置为iframe名称并提交原始表单。

答案 1 :(得分:1)

我一直在寻找同样的问题,我想,我找到了一个解决方案,适用于Firefox和Chrome,可能在IE 10及以上版本(这里需要进行一些测试)

解决方案有点难看因为我使用了框架集。但这是我到目前为止找到的唯一解决方案。

用例是: 我们有一个包含产品目录的网站,编辑可以为每个产品上传视频。

视频上传需要很长时间,所以我一直在寻找解决方案,在您选择视频后开始上传,您可以导航到其他产品并上传其他文件,而无需等到第一个下载完成。

该测试基于其他一些工作:

https://stackoverflow.com/a/1186309/2248340 https://stackoverflow.com/a/105074/2248340

工作原理:

如果按提交,表单数据将被放置在一个对象中。在此对象中也是选定的文件列表。

此对象将在上传帧中推送数组请求。

这里运行看门狗并查看是否有新请求(status = 0) 如果它找到一个新的上传开始。

这是我尝试的测试项目:

框架集:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>Insert title here</title>
</head>
<frameset rows="*,100">
    <frame id="start" name="start" src="start.html">
    <frame id="upload" name="upload" src="frame.html">
</frameset>
<noframes>
    <body>
        <a href="start.html">please use this</a>
    </body>
</noframes>
</html>

的start.html

<!DOCTYPE html>
<html>
   <head>
    <meta charset="UTF-8">
    <title>Start</title>
    <script src="../js/jquery-1.11.3.min.js" ></script>
    <script>
    var files;
    $.fn.serializeObject = function()
    {
        var o = {};
        var a = this.serializeArray();
        $.each(a, function() {
            if (o[this.name] !== undefined) {
                if (!o[this.name].push) {
                    o[this.name] = [o[this.name]];
                }
                o[this.name].push(this.value || '');
            } else {
                o[this.name] = this.value || '';
            }
        });
        return o;
    };

    var UploadRequest=function(f)
    {
        var o= {};
        o['guid']=guid();
        o['action']=$('form').attr('action');
        o['files']=files;
        o['values']=$('form').serializeObject();
        o['status']=0;
        return o;
    }

    function fileSelect( e){
        files=e.target.files;
        return false;
    }

    </script>
  </head>
  <body>
      <form id="test" action="phpinfo.php">
      <input  name="test" >
      <input type="hidden"  name="h1" value="2">
      <input type="file"  name="uploadfile" onchange="fileSelect(event)">
      <input type="submit" value="upload‚" > 
      </form>
      <script>
      var olddogcounter=localStorage['uploadwatchdog'];
      var check=false;
      function guid() {
          function s4() {
            return Math.floor((1 + Math.random()) * 0x10000)
              .toString(16)
              .substring(1);
          }
          return s4() + s4() + '-' + s4() + '-' + s4() + '-' +
            s4() + '-' + s4() + s4() + s4();
        }

      $(function() {
            $('#test').submit(function() {
                var request=new UploadRequest();
                parent.upload.requests.push(request);  
                return false;
            });
        });
      </script>
      <a href="test.html" >test</a>
  </body>
</html>

和上传框架:

<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title>frame</title>

</head>
<body>
    <h1>frame</h1>

    <iframe id="response" width="100%" height="200"></iframe>

    <script>
      var requests=new Array();
      var counter=0;
      function watchdog()
      {
          for(var i=0; i<requests.length; i++)
          {
              var request=requests[i];
              if(request.status==0)
              {
                  alert("watchdog :"+dump(request));
                  request.status=1;
                  uploadFile(request); 
              }
          }
      }

      function uploadFile(request)
      {
        var url = request.action;
        var xhr = new XMLHttpRequest();
        var fd = new FormData();
        xhr.open("POST", url, true);
        xhr.onreadystatechange = function() {
            if (xhr.readyState == 4 && xhr.status == 200) {
                iframe=document.getElementById("response");
                iframe.src="data:text/html;charset=utf-8," + escape(xhr.responseText);
            }
        };
        if(request.files.length>1)
        {
           for(var i=0; i<request.files.length;i++)
           {
                var file=request.files[i];
                fd.append("upload_file[]", file);
            }
        }
        else
        {
           var file=request.files[0];
           fd.append("upload_file",file );
        }
        for( var key in request.values)
        {
           fd.append(key,request.values[key] );
        }
        xhr.send(fd);
      }
      window.setInterval(watchdog,2000);
  </script>
</body>
</html>

解决方案尚未完成,但我认为这是一个很好的起点。

TODO: - 在列表中显示上载的名称 - 上传后从数组请求中删除请求 - 显示上传的progess栏 - 一些错误处理