zoukankan      html  css  js  c++  java
  • 各种文件上传方式

    上传文件

    1、Form表单上传

    接下来我们使用HTML标签来创建文件上传表单,以下为要注意的点:

    • form表单 method 属性必须设置为 POST 方法 ,不能使用 GET 方法。
    • form表单 enctype 属性需要设置为 multipart/form-data

      enctype 属性规定在发送到服务器之前应该如何对表单数据进行编码。默认地,表单数据会编码为 “application/x-www-form-urlencoded”。就是说,在发送到服务器之前,所有字符都会进行编码(空格转换为 “+” 加号,特殊符号转换为 ASCII HEX 值)。而当设置了该编码格式时,不能直接上传文件。因此,这里我们使用另外一种编码格式,即multipart/form-data,该编码格式不对数据进行编码,而是直接上传二进制数据,form里面的input的值以二进制的方式传过去。

    <!DOCTYPE html>
    <html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"/>
        <title>上传文件</title>
    </head>
    <body>
        <form id="my_form" name="form" action="/index" method="POST"  enctype="multipart/form-data" >
            <input name="fff" id="my_file"  type="file" />
            <input type="submit" value="提交"  />
        </form>
    </body>
    </html>
    index.html
    Python

    注意:这种传统的表单上传,属于"同步上传"。也就是说,点击上传按钮后,网页"锁死",用户只能等待上传结束,然后浏览器刷新,跳到表单的action属性指定的网址。

    2、AJAX上传

      对于传统的表单上传,如果我们上传的是一份大文件的话,那你就在那里干等着吧。如此low的用户体验肯定不是我们想要的。那我们该怎么办呢?这时候我们就要用到Ajax“异步上传”了

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <input type="file" id="img" />
        <input type="button" onclick="UploadFile();" />
        <script>
    //创建一个表单对象
            function UploadFile(){
                var fileObj = document.getElementById("img").files[0];
    //主要用的是FormData对象,它能够构建类似表单的键值对。FormData可以凭空创建一个对象,然后往这个对象里面添加数据,然后直接提交
                var form = new FormData();
                form.append("k1", "v1");
                form.append("fff", fileObj);
    
                var xhr = new XMLHttpRequest();
                xhr.open("post", '/index', true);
                xhr.send(form);
            }
        </script>
    </body>
    </html>
    HTML - XMLHttpRequest
    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <input type="file" id="img" />
        <input type="button" onclick="UploadFile();" />
        <script>
            function UploadFile(){
                var fileObj = $("#img")[0].files[0];
                var form = new FormData();
                form.append("k1", "v1");
                form.append("fff", fileObj);
    
                $.ajax({
                    type:'POST',
                    url: '/index',
                    data: form,
                    cache: false
                    processData: false,  // tell jQuery not to process the data
                    contentType: false,  // tell jQuery not to set contentType
                    success: function(arg){
                        console.log(arg);
                    }
                })
            }
     /*cache
        cache设为false可以禁止浏览器对该URL(以及对应的HTTP方法)的缓存。 jQuery通过为URL添加一个冗余参数来实现。
        该方法只对GET和HEAD起作用,然而IE8会缓存之前的GET结果来响应POST请求。 这里设置cache: false是为了兼容IE8。
    
    contentType
        jQuery中content-type默认值为application/x-www-form-urlencoded, 因此传给data参数的对象会默认被转换为query string(见HTTP 表单编码 enctype)。
        我们不需要jQuery做这个转换,否则会破坏掉multipart/form-data的编码格式。 因此设置contentType: false来禁止jQuery的转换操作。
    
    processData
        jQuery会将data对象转换为字符串来发送HTTP请求,默认情况下会用 application/x-www-form-urlencoded编码来进行转换。 我们设置contentType: false后该转换会失败,因此设置processData: false来禁止该转换过程。
        我们给的data就是已经用FormData编码好的数据,不需要jQuery进行字符串转换。
        */
        </script>
    </body>
    </html>
         
    HTML - jQuery

      jQuery文件上传方式依赖于FormData对象, 这是XMLHttpRequest Level 2接口, 需要 IE 10+, Firefox 4.0+, Chrome 7+, Safari 5+, Opera 12+

    这意味着对于低版本浏览器只能使用直接提交文件表单的形式, 但提交大文件表单页面会长时间不响应,如果希望在低版本浏览器中解决该问题, 就只能使用别的方式来实现了,比如很多支持多文件和上传进度的Flash插件。

    iframe上传

    在HTML5没有出现之前,只能用iframe来实现“异步上传”。用户点击submit时,动态插入一个iframe元素

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    </head>
    <body>
        <form id="my_form" name="form" action="/index" method="POST"  enctype="multipart/form-data" >
            <div id="main">
                <input name="fff" id="my_file"  type="file" />
                <input type="button" name="action" value="Upload" onclick="redirect()"/>
                <iframe id='my_iframe' name='my_iframe' src=""  class="hide"></iframe>
            </div>
        </form>
    
        <script>
            function redirect(){
                document.getElementById('my_iframe').onload = Testt;  //iframe加载完成后立马执行
                document.getElementById('my_form').target = 'my_iframe'; //,它为表单添加target属性,指向动态插入的iframe窗口,这使得上传结束后,服务器将结果返回iframe窗口,所以当前页面就不会跳转了
                document.getElementById('my_form').submit();
    
            }
            
            function Testt(ths){
                var t = $("#my_iframe").contents().find("body").text();
                console.log(t);
            }
        </script>
    </body>
    </html>
    HTML - iframe
    #!/usr/bin/env python
    # -*- coding:utf-8 -*-
    
    import tornado.ioloop
    import tornado.web
    
    
    class MainHandler(tornado.web.RequestHandler):
        def get(self):
    
            self.render('index.html')
    
        def post(self, *args, **kwargs):
            file_metas = self.request.files["fff"]
            # print(file_metas)
            for meta in file_metas:
                file_name = meta['filename']
                with open(file_name,'wb') as up:
                    up.write(meta['body'])
    
    settings = {
        'template_path': 'template',
    }
    
    application = tornado.web.Application([
        (r"/index", MainHandler),
    ], **settings)
    
    
    if __name__ == "__main__":
        application.listen(8000)
        tornado.ioloop.IOLoop.instance().start()
    Python
    <script type="text/javascript">
     
        $(document).ready(function () {
     
            $("#formsubmit").click(function () {
     
                var iframe = $('<iframe name="postiframe" id="postiframe" style="display: none"></iframe>');
     
                $("body").append(iframe);
     
                var form = $('#theuploadform');
                form.attr("action", "/upload.aspx");
                form.attr("method", "post");
     
                form.attr("encoding", "multipart/form-data");
                form.attr("enctype", "multipart/form-data");
     
                form.attr("target", "postiframe");
                form.attr("file", $('#userfile').val());
                form.submit();
     
                $("#postiframe").load(function () {
                    iframeContents = this.contentWindow.document.body.innerHTML;
                    $("#textarea").html(iframeContents);
                });
     
                return false;
     
            });
     
        });
     
    </script>
     
     
    <form id="theuploadform">
        <input id="userfile" name="userfile" size="50" type="file" />
        <input id="formsubmit" type="submit" value="Send File" />
    </form>
     
    <div id="textarea">
    </div>
    扩展:基于iframe实现Ajax上传示例
    $('#upload_iframe').load(function(){
                        var iframeContents = this.contentWindow.document.body.innerText;
                        iframeContents = JSON.parse(iframeContents);
                       
                    })
    View Code
    function bindChangeAvatar1() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    $('#prevViewImg')[0].src = window.URL.createObjectURL(file_obj)
                })
            }
    
            function bindChangeAvatar2() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    var reader = new FileReader();
                    reader.readAsDataURL(file_obj);
                    reader.onload = function (e) {
                        $('#previewImg')[0].src = this.result;
                    };
                })
            }
    
            function bindChangeAvatar3() {
                $('#avatarImg').change(function () {
                    var file_obj = $(this)[0].files[0];
                    var form = new FormData();
                    form.add('img_upload', file_obj);
    
                    $.ajax({
                        url: '',
                        data: form,
                        processData: false,  // tell jQuery not to process the data
                        contentType: false,  // tell jQuery not to set contentType
                        success: function (arg) {
    
                        }
                    })
                })
            }
    
            function bindChangeAvatar4() {
                $('#avatarImg').change(function () {
                    $(this).parent().submit();
    
                    $('#upload_iframe').load(function () {
                        var iframeContents = this.contentWindow.document.body.innerText;
                        iframeContents = JSON.parse(iframeContents);
                        if (iframeContents.status) {
                            $('#previewImg').attr('src', '/' + iframeContents.data);
                        }
                    })
    
                })
            }
    其他

    3、进度条

    XMLHttpRequest第二版还定义了一个progress事件,可以用来制作进度条。

    首先,在页面中放置一个HTML元素progress。

     <progress id="uploadprogress" min="0" max="100" value="0">0</progress>

    然后,定义progress事件的回调函数。

    xhr.upload.onprogress = function (event) {
        if (event.lengthComputable) {
          var complete = (event.loaded / event.total * 100 | 0);
          var progress = document.getElementById('uploadprogress');
          progress.value = progress.innerHTML = complete;
        }
      };
    View Code

    注意,progress事件不是定义在xhr,而是定义在xhr.upload,因为这里需要区分下载和上传,下载也有一个progress事件。

    4、图片预览

    如果上传的是图片文件,利用File API,我们可以做一个图片文件的预览。这里主要用到FileReader对象

     // 检查是否支持FileReader对象
      if (typeof FileReader != 'undefined') {
        var acceptedTypes = {
          'image/png': true,
          'image/jpeg': true,
          'image/gif': true
        };
        if (acceptedTypes[document.getElementById('upload').files[0].type] === true) {
          var reader = new FileReader();
          reader.onload = function (event) {
            var image = new Image();
            image.src = event.target.result;
            image.width = 100;
            document.body.appendChild(image);
          };
        reader.readAsDataURL(document.getElementById('upload').files[0]);
        }
      }
    View Code

    5、拖放上传

    最后,利用HTML5的拖放功能,实现拖放上传。

    先在页面中放置一个容器,用来接收拖放的文件。

     <div id="holder"></div>

    对它设置样式:

     #holder {
        border: 10px dashed #ccc;
        width: 300px;
        min-height: 300px;
        margin: 20px auto;
      }
      #holder.hover {
        border: 10px dashed #0c0;
      }
    View Code

    拖放文件的代码,主要是定义dragover、dragend和drop这三个事件。

     // 检查浏览器是否支持拖放上传。
      if('draggable' in document.createElement('span')){
        var holder = document.getElementById('holder');
        holder.ondragover = function () { this.className = 'hover'; return false; };
        holder.ondragend = function () { this.className = ''; return false; };
        holder.ondrop = function (event) {
          event.preventDefault();
          this.className = '';
          var files = event.dataTransfer.files;
          // do something with files
        };
      }
    View Code

    参考:http://www.ruanyifeng.com/blog/2012/08/file_upload.html

    参考:http://www.cnblogs.com/wupeiqi/articles/5702910.html

  • 相关阅读:
    linux日常管理-screen
    linux日常管理-xarge_exec
    linux日常管理-linux日志
    linux日常管理-系统服务
    linux命令-任务计划-cron
    linux日常管理-防火墙netfilter工具-iptables-3
    linux日常管理-防火墙netfilter工具-iptables-2
    开启80端口
    linux日常管理-防火墙netfilter工具-iptables-1
    随机4位验证码
  • 原文地址:https://www.cnblogs.com/freely/p/6771578.html
Copyright © 2011-2022 走看看