zoukankan      html  css  js  c++  java
  • 文件上传---form表单,ajax,jquery,以及iframe无刷新上传 (processData,contentType讲解)

    服务端程序:

    import tornado.web
    import os
    
    IMG_LIST=[]
    
    class IndexHandler(tornado.web.RequestHandler):
        def get(self):
    
            self.render('index.html',list_img=IMG_LIST)
    
        def post(self, *args, **kwargs):
            name=self.get_argument('name')
            pwd=self.get_argument('pwd')
            #fn=self.get_argument('img')
            file_meta=self.request.files['img']
            for meta in file_meta:
                file_name=meta['filename']
                file_path=os.path.join('img',file_name);
                IMG_LIST.append(file_path)
                with open(os.path.join('static',file_path),"wb") as fp:
                    fp.write(meta['body'])
    
            self.write('{"status":1,"message":"mmm"}')
    
    settings ={
        'template_path':'views',
        'static_path':'static',
        'static_url_path':'sss'
    }
    
    application = tornado.web.Application([
        (r"/index",IndexHandler),
    ],**settings)
    
    
    if __name__=="__main__":
        application.listen(8080)
        tornado.ioloop.IOLoop.instance().start()
    View Code

    form表单:注意加上enctype="multipart/form-data"

        <form action="/index" method="post" enctype="multipart/form-data">
            <input type="text" name="name"/>
            <input type="text" name="pwd">
            <input type="file" name="img" id="img">
            <input type="submit">
        </form>

    js使用ajax上传:

        <button onclick="uploadFile();">ajax上传文件</button>
        function uploadFile(){
            //获取文件对象
            var fileobj=document.getElementById("img").files[0];
            //创建form表单对象
            var form=new FormData();
            form.append('name', document.getElementsByTagName('input')[0].value);
            form.append('pwd', document.getElementsByTagName('input')[1].value);
            form.append('img',fileobj);
    
            var xhr=new XMLHttpRequest();
            xhr.open('post','/index',true);
            xhr.send(form);
        }

    jquery上传文件:

        <button onclick="uploadFile2();">jquery上传文件</button>
        function  uploadFile2() {
            //先获取文件对象
            var fileObj=$("#img")[0].files[0];
            var form=new FormData();
            form.append('name', document.getElementsByTagName('input')[0].value);
            form.append('pwd', document.getElementsByTagName('input')[1].value);
            form.append('img',fileObj);
    
            $.ajax({
                type:'post',
                url:'/index',
                data:form,
                processData:false,
                contentType:false,
                dataType:'text',
                success:function(data){
                    console.log(data);
                }
            })
        }

    其中主要注意:

    processData设置为false。因为data值是FormData对象,不需要对数据做处理。

    processData
    类型:Boolean
    默认值: true。默认情况下,通过data选项传递进来的数据,如果是一个对象(技术上讲只要不是字符串),都会处理转化成一个查询字符串,以配合默认内容类型 "application/x-www-form-urlencoded"。如果要发送 DOM 树信息或其它不希望转换的信息,请设置为 false。

     补充:在Django下:

    data:{a:1,b:2,csrfmiddlewaretoken:'{{ csrf_token }}'},
                
    默认获取为:processData:true
    <QueryDict: {u'a': [u'1'], u'csrfmiddlewaretoken': [u'darHnLiXqB0f4r25nenCAsNdMhT1ms3qTes1l8c509Lu7uWeGg4IBCZXmLpXKkzW'], u'b': [u'2']}>
    processData:false

    此时:获取数据类型为 <QueryDict: {u'[object Object]': [u'']}>

    相对于:

    processData声明当前的data数据是否进行转码或预处理,默认为true,即预处理;
                 # 如果为false,那么对data:{a:1,b:2}会调用json对象的toString()方法,即{a:1,b:2}.toString()
                 # ,最后得到一个[object,Object]形式的结果。   
           #如果为false,会将未处理的数据(类型为对象)传递过去,而且没有对应的值,只有该对象,所以会在服务器获得{u'[object Object]': [u'']}样式的数据 # {
    "1":"111","2":"222","3":"333"}.toString();//[object Object] # 该属性的意义在于,当data是一个dom结构或者xml数据时,我们希望数据不要进行处理,直接发过去, # 就可以讲其设为true。

     补错:ajax对于post传输数据的处理方法并不是简单的toString,而是其他方法:参见源码:

    s = jQuery.ajaxSetup( {}, options ),
    // Convert data if not already a string
    if ( s.data && s.processData && typeof s.data !== "string" ) {
        s.data = jQuery.param( s.data, s.traditional );  #traditional是否允许传递迭代数据
    }

    所以我们测试processData时可以使用:

    正常使用:

        function send_ajax(){
            console.log(tt)
            $.ajax({
                type:'POST',
                url:'/get_ajax',
                data:{a: 1, b: 2, csrfmiddlewaretoken: '{{ csrf_token }}'},
                processData:true,   #默认为true,会对上面的data对象进行处理,转换为字符串
                dataType:'text',
                success:function(data){
                    console.log(data);
                }
            })
        }

    稍作处理:我们自己对对象数据进行处理,转换为字符串,不需要非得将processData设置为true,也可以将数据传递过去(不需要注释掉settings.py中'django.middleware.csrf.CsrfViewMiddleware',了,也可以传递过去)

    function send_ajax(){
            tt = {a: 1, b: 2, csrfmiddlewaretoken: '{{ csrf_token }}'};
            tt = jQuery.param( tt, false );
            console.log(tt)
         //a=1&b=2&csrfmiddlewaretoken=Pd6dDAurbbEemf5B6UGUrlAlXvE3BWY6zWA4yeCPR9jbwNuqb62u3OZvuhL5RAff $.ajax({ type:
    'POST', url:'/get_ajax', data:tt, processData:false, dataType:'text', success:function(data){ console.log(data); } }) }

    contentType设置为false。因为是由<form>表单构造的FormData对象,且已经声明了属性enctype="multipart/form-data",所以这里设置为false

    在 jquery 的 ajax 中, contentType都是默认的值:application/x-www-form-urlencoded,这种格式的特点就是,name/value 成为一组,每组之间用 & 联接,而 name与value 则是使用 = 连接。

    不需要设置的适合使用false

    contentType:默认值: "application/x-www-form-urlencoded"。发送信息至服务器时内容编码类型。
                 # 用来指明当前请求的数据编码格式;urlencoded:?a=1&b=2;如果想以其他方式提交数据,
                 # 比如contentType:"application/json",即向服务器发送一个json字符串: 
                 #   $.ajax("/ajax_get",{
                 # 
                 #      data:JSON.stringify({
                 #           a:22,
                 #           b:33
                 #       }),
                 #       contentType:"application/json",
                 #       type:"POST",
                 #       
                 #   });                          //{a: 22, b: 33}
    
                 # 注意:contentType:"application/json"一旦设定,data必须是json字符串,不能是json对象

     traditional:允许传递迭代数据:

     traditional:一般是我们的data数据有数组时会用到 :data:{a:22,b:33,c:["x","y"]}, 
                  traditional为false会对数据进行深层次迭代;   
     

     更多参数请看:http://jquery.cuishifeng.cn/jQuery.Ajax.html

    iframe:上传几乎兼容所有浏览器

    <head>
        <meta charset="UTF-8">
        <title>Title</title>
        <style>
            .hide{
                display:none;
            }
        </style>
        <script src="{{static_url('js/jquery.js')}}"></script>
    </head>
    <body>
        <form id="my_form" action="/index" method="POST" enctype="multipart/form-data">
            <div id="main">
                <input name="name" type="text"/>
                <input name="pwd" type="text"/>
                <input name="img" id="img" type="file"/>
                <input type="button" name="action" value="Upload" onclick="redirect();">
                <iframe id="my_iframe" name="my_iframe" src="" class="hide"></iframe>
            </div>
        </form>
    </body>
    </html>
    <script>
        function redirect() {
            document.getElementById("my_iframe").onload=Test();
            //target-->目标提交地点iframe,iframe提交页面不刷新
            document.getElementById('my_form').target='my_iframe';   #这里可以直接写在HTML中,在form中添加上target="my_iframe"即可
            document.getElementById('my_form').submit();
        }
        function Test() {
            var t=$("#my_iframe").contents().find('body').text();  #表单提交以后会触发test函数,这里去获取服务端回送的数据 
        //var t=this.contentWindow.document.body.innerHtml;  也可以 console.log(t);
        
    var content=this.contentWindow.document.body.innerHTML;
    var obj = JSON.parse(content);    #服务器发送过来的是json数据,包含自定义状态码,图片路径
    
    var tag = document.createElement("img");
    tag.src = obj.data;  #data中是图片路径
    
    $("#my_iframe").empty().append(tag); #先清空原来数据,在加入新的标签
    iframe显示图片
        }
    </script>

    如果给定表示 DOM 元素集合的 jQuery 对象,.contents() 方法允许我们检索 DOM 树中的这些元素的直接子节点,并用匹配元素构造新的 jQuery 对象。.contents() 和 .children() 方法类似,不同的是前者在结果 jQuery 对象中包含了文本节点以及 HTML 元素。

    .contents() 方法也可以用于获得 iframe 的内容文档,前提是该 iframe 与主页面在同一个域。而children()不能用于iframe 

  • 相关阅读:
    Git上传文件、文件夹到github
    Git管理修改、撤销修改、删除文件
    Git使用教程之从远程库克隆项目(四)
    Git使用教程之在github上创建项目(三)
    Git使用教程之SSH连接方式配置(二)
    Git使用教程之新手也能看懂(一)
    JS字符串截取 “指定字符” 前面和后面的内容!
    vue.js 实现点击展开收起动画
    最简单的手机预览WEB移动端网页的方法
    vue-cli中浏览器图标的配置
  • 原文地址:https://www.cnblogs.com/ssyfj/p/8533287.html
Copyright © 2011-2022 走看看