上传文件

上传文件

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

                })

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;
    }
  };

注意,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]);
    }
  }

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;
  }

拖放文件的代码,主要是定义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
    };
  }

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

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

时间: 2024-11-07 16:58:36

上传文件的相关文章

input type=&#39;file&#39; 上传文件 判断图片的大小是否合格与witdh 和 height 是否合格

function CheckFiles(obj) { var array = new Array('gif', 'jpeg', 'png', 'jpg'); //可以上传的文件类型 if (obj.value == '') { alert("让选择要上传的图片!"); return false; } else { var fileContentType = obj.value.match(/^(.*)(\.)(.{1,8})$/)[3]; //这个文件类型正则很有用:) var isE

input type=file 上传文件,同一个文件第二次上传无反应

用input file上传文件,掉用onchange方法时,多次上传同一个文件时功能失效,不会发送ajax请求 input[type=file]使用的是onchange去做,onchange监听的为input的value值,只有再内容发生改变的时候去触发,而value在上传文件的时候保存的是文件的内容,你只需要在上传成功的回调里面,将当前input的value值置空即可.event.target.value=“”: 设为空之后在次点击就可实现同一文件多次上传操作 原文地址:https://www

HTML &lt;input type=&quot;file&quot;&gt;上传文件——结合asp.net的一个文件上传示例

HTML的代码:(关键是要在form里设置enctype="multipart/form-data",这样才能在提交表单时,将文件以二进制流的形式传输到服务器) 一. <form id="form1" action="test.aspx" method="post" enctype="multipart/form-data"> <div> <input type="f

input[type=file]上传文件(格式判断、文件大小、上传成功后操作)

var isUploadImg = false; //在input file内容改变的时候触发事件******************上传图片 $('#filed').change(function(){ var file = $('#filed').get(0).files[0]; var fileSize = file.size,fileType = file.type; if (file.name.lastIndexOf('.')==-1){ //如果不存在"." $.dialo

&lt;input type=&quot;file&quot;&gt;上传文件

string filename = this.loading.Value; if (filename != "") { string urlb = Server.MapPath("images/banner/"); var img = Context.Request.Files["loading"]; img.SaveAs(urlb + filename); url = filename; }

input type=file上传控件老问题

// 1.用INPUT控制上传文件时,点击INPUT控件出现文件选择框. // 2.如果在手机上使用时,一般不会出现这种较丑的 // 3.于是就自然想到将控件隐藏,然后用一个按钮代替,点击按钮时在函数里使用脚本触发INPUT控件的 // 4.结果发现无效,无法使用JS触发INPUT的控件.(在PC端有的浏览器可以,在手机浏览器中有的安卓机可以,苹果机不行) <form> <input name="photos" type="file" accept

使用VUE脚手架+HTML5 input type = file 上传视频

上传视频思路 HTML:1. 在这里首先会用到html5标签 video 音频/视频2. input type = file CSS 给一些样式 *******JS js实现思路:1.通过原生的方法获取上传文件(input)标签 并且交给一个变量.2.通过原生的方法获取音频标签并且交给一个变量.3.通过input标签得到自身的的files[0] :而我们对input.files[0]数据需要处理,于是写一个方法.并且把input.files[0]传进去. 举个栗子: 4.处理数据的具体步骤:在g

&lt;input type=file&gt;上传唯一控件

值得注意的是:当一个表单里面包含这个上传元素的时候,表单的enctype必须指定为multipart/form-data,method必须指定为post,浏览器才会认识并正确执行.但是还有一点,浏览器只允许用户点击<input type="file">来选择本地文件,用JavaScript对<input type="file">的value赋值是没有任何效果的.当用户选择了上传某个文件后,JavaScript也无法获得该文件的真实路径:但是有

使用js清空input file上传文件的内容

html页面代码如下: <input id="file_input" type="file" onchange="upLoadFile(this)" value="" />js的代码如下,可以直接将上传文件input按钮的内容直接清空: var obj=document.getElementById('file_input');obj.outerHTML=obj.outerHTML; ---------------

mvc4 使用input:file上传文件

@using (Html.BeginForm("AddNews", "NewsMgr", FormMethod.Post, new { enctype = "multipart/form-data" })) 前台页面上使用form提交,但是HtmlAttribute必须有这个属性 enctype = "multipart/form-data" 否则上传时提交到后台的Request.Files一直为空,count是0. 后台页面