如何通过ajax(没有jquery)发送multipart/form-data表单内容?

IT技术 javascript ajax
2021-03-14 01:25:43

我试图在不重新加载页面的情况下发送一些表单,并且我试图了解幕后细节,因此不使用任何 JavaScript 库:

var http = createRequestObject();
function createRequestObject() {
    var objAjax;
    if (window.XMLHttpRequest)
    {// code for IE7+, Firefox, Chrome, Opera, Safari
        objAjax=new XMLHttpRequest();
    }
    else
    {// code for IE6, IE5
        objAjax=new ActiveXObject("Microsoft.XMLHTTP");
    }
    return objAjax;
}

function display_progress() { ... }    

function upload_file() {
    var request = 'UploaderServlet';
    http.open('post', request);
    http.onreadystatechange = display_progress;
    http.send(null); // HERE PROBABLY THE DATA SHOULD BE SENT
}

<form enctype="multipart/form-data" id="upload_form" name="upload_form" method="POST" action="UploaderServlet" onsubmit="upload_file(); return false;" target="upload_target">
Choose a file <br />  
<input name="file" size="27" type="file" id="file" /> <br/> 
<input type="submit" name="uploadSubmitButton" value="Upload" /><br /> 
<br />  
</form> 

<iframe id="upload_target" name="upload_target" src="#" style="width:0;height:0;border:0px solid #fff;"></iframe>

调用了upload_file(),但如果我做对了,则不会发送数据。请就发送数据的正确方式提出建议。

3个回答

在表单中传递属性 {url:"",method:"",data:{...},callback:function(){}}

var ajax=function(){
  try{
    var xml       =new XMLHttpRequest();
    var args      =arguments;
    var context   =this;
    var multipart ="";

    xml.open(args[0].method,args[0].url,true);

    if(args[0].method.search(/post/i)!=-1){
      var boundary=Math.random().toString().substr(2);
      xml.setRequestHeader("content-type",
                  "multipart/form-data; charset=utf-8; boundary=" + boundary);
      for(var key in args[0].data){
        multipart += "--" + boundary
                   + "\r\nContent-Disposition: form-data; name=" + key
                   + "\r\nContent-type: application/octet-stream"
                   + "\r\n\r\n" + args[0].data[key] + "\r\n";
      }
      multipart += "--"+boundary+"--\r\n";
    }

    xml.onreadystatechange=function(){
      try{
        if(xml.readyState==4){
          context.txt=xml.responseText;
          context.xml=xml.responseXML;
          args[0].callback();
        }
      }
      catch(e){}
    }

    xml.send(multipart);
  }
  catch(e){}
}

如果你想得到回复,你可以使用这个

var response={};
ajax.call(response,{...args...})

并且您可以通过response.txt检索所有数据response.xml

更新有点晚

至于@Varun 关于<input type='file'>上传的问题,此代码无法直接处理文件上传,为了使用此代码发送文件,您需要使用File API原始文件数据进行预处理以获得非二进制流(如 base64 或任何其他类似 bin2hex 的形式)。

但是,由于是 2015 年,我可以建议从多部分流的构建转向更强大的东西,例如FormData API

无法理解我们将在数据中提供什么 <input type=file
2021-05-20 01:25:43

XMLHttpRequest除了null您传入的代码之外,您的代码看起来还不错send您需要传入一个包含要发送的数据的字符串(当然是正确编码的)。

请注意,如果您想发送input[type=file]字段引用的文件,则需要将其读入内存,唯一的方法是使用新的File API,该API尚未得到广泛支持。

如果您尝试发送带有进度条的文件,您可以通过在支持 File API 的浏览器上发布您通过 File API 读取的文件块来实现,可能会退回到基于 Flash 的上传器,例如如果浏览器不支持 File API,则swfupload,如果浏览器不支持 Flash,则回退到正常的表单提交。

@BreakPhreak:他们正在 iframe 中提交表单,请参阅github.com/yui/yui2/blob/master/src/connection/js/... 中uploadFile函数
2021-04-24 01:25:43
首先,我确实为进度条提供了服务器端支持。我仍然无法了解数据的发送方式。我的意思是,我进去看了YUI源(yui.yahooapis.com/2.9.0/build/connection/connection_core-min.js ”,_setForm功能),这看起来像一场噩梦:)
2021-04-28 01:25:43
感谢您的快速答复。johnboy.com/scripts/php-upload-progress-meter/progress.phps - 在这里,YUI 以某种方式设法在没有文件 API / flash 等的情况下成功发送表单数据。
2021-05-07 01:25:43
@BreakPhreak:啊,是的,那是另一种方式,它需要服务器端支持:您进行标准表单发布,然后(单独)轮询服务器,询问到目前为止收到了多少数据,并以这种方式显示进度指示器。但当然,这需要服务器端支持。(它还要求浏览器允许您在运行表单 POST 的同时执行 ajax 调用,但大多数会。)不过,如果您控制事务的双方,仍然很酷。
2021-05-21 01:25:43

需要传入一个包含要发送的数据的字符串(当然是正确编码的)。

w 文件 API,您的 XMLHtth 尚未得到广泛支持。

如果您在支持 File API 的浏览器上尝试 le API,也许回退到基于 Flash 的上传器 likpRequest 代码看起来不错,除了您传递给 send.e swfupload 的 null 如果浏览器不支持File API,如果浏览器不支持发送带有进度条的文件,则退回到正常的表单提交,您可以通过发布您通过 Fit Flash 阅读的块来实现。