博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
利用FormData进行ajax上传文件
阅读量:6943 次
发布时间:2019-06-27

本文共 9836 字,大约阅读时间需要 32 分钟。

hot3.png

个人实现方式:

html代码

{% csrf_token %}
Browse

js代码:

$(document).ready(function() {    //alert($("#file").parent().get(0).tagName);     var uploadForm = $("#uploadForm").validate({        // Rules for form validation        rules : {            uoload :{                required : true	    }        },        // Messages for form validation        messages : {            uoload :{                required : '上传文件不能为空'            }        },        submitHandler: function(form){            //如果不加[0]:Argument 1 of FormData.constructor does not implement interface HTMLFormElem            //$('form') returns a jQuery object, but we need to pass a HTML element to FormData. `[0]` does that for us. It is the same as calling $('form').get(0)            var fd = new FormData($("#uploadForm")[0]);            //可以传额外的参数            fd.append("CustomField", "This is some extra data");            $.ajax({                url: "/build/configAdd/",                type: "POST",                data: fd,                processData: false,  // 告诉jQuery不要去处理发送的数据                contentType: false,   // 告诉jQuery不要去设置Content-Type请求头                error: function(msg) {                    closeMyDialog($("#setAddId"));                    showSuccessMsg("添加配置失败");                },                success: function(msg){                    closeMyDialog($("#setAddId"));                    showSuccessMsg(msg);                }            });        },        // Do not change code below        //modified by yf 2016_06_17        errorPlacement : function(error, element) {	    if("SPAN" == element.parent().get(0).tagName){	        error.insertAfter(element.parent().next());	        error.css("color","#D56161");	        error.css("font-size","11px");	        error.css("line-height","15px");	        error.css("font-style","normal");	    }else{	        error.insertAfter(element.parent());	    }        }    });})

后台python代码

@required_login(redirect="/build/login/")@csrf_exemptdef configAddHandler(request):    if request.method == "GET":        return render(request, 'auto_config/configAdd.html')    elif request.method == "POST":        buf = request.FILES.get('uoload', None)        if buf:            f = buf.read()            print type(f)            BASE_DIR = os.path.dirname(__file__)            #保存上传的excel,以做历史查询            try:                save_file(BASE_DIR, str(buf), f)                return HttpResponse("上传成功")            except:                return HttpResponse("上传失败")        else:            return HttpResponse("上传失败")def mkdir(path):    # 去除左右两边的空格u    path=path.strip()    # 去除尾部 \符号    path=path.rstrip("\\")    if not os.path.exists(path):        os.makedirs(path)    return path#工具函数,保存上传的文件def save_file(path, file_name, data):    if data == None:        return mkdir(path)    if(not path.endswith("/")):        path=path+"/"    fileObj=open(path+file_name, "wb")    fileObj.write(data)    fileObj.flush()    fileObj.close()

以下是引用的别人和官方的文章

########################################################################

用到两个对象

第一个对象:FormData

第二个对象:XMLHttpRequest

目前新版的Firefox 与 Chrome 等支持HTML5的浏览器完美的支持这两个对象,但IE9尚未支持 FormData 对象,还在用IE6 ? 只能仰天长叹....

有了这两个对象,我们可以真正的实现Ajax方式上传文件。

示例代码:

 

    Html5 Ajax 上传文件    

 

 

很简洁的代码,便可以达到Ajax方式上传文件,上面的代码中使用<input type="file" />这种传统的选择文件的方法产生文件对象,HTML5还支持使用多种更灵活的方式,如拖拽文件到指定的元素上产生。

Ajax已成功上传文件,但这时我们会想到一个问题,如何显示进度条?带着这个问题,脑子会想到,Flash? 浏览器插件?。

NO,现在不需要这些东西了。

开始着手,先做一个进度条,进度条也很简单,使用HTML5 新加的标签:

 

这个在浏览器中便会呈现了一个进度条,现在我们要做的就是在上传的时候,实时的去改变它的Value值,然后进度显示的问题便交给它了。

我们的服务器端无需修改,只需要在JS中XHR对象加一个事件。

xhr.upload.addEventListener("progress", progressFunction, false)

progressFunction 被调用的时候会传进一个事件对象,这个对象有两个属性,一个就是loaded 一个是total ,分别代表,已上传的值,和总要上传的值。

这正是我们需要的,所以这个方法,可以这样写:

 

function progressFunction(evt) {            var progressBar = document.getElementByIdx_x_x("progressBar");            if (evt.lengthComputable) {                progressBar.max = evt.total;                      progressBar.value = evt.loaded;                           }        }

 

这样便可以完成,上传进度显示了。

如下针对上面的第一个示例代码,做一个调整:

示例代码2,带进度显示:

    Html5 Ajax 上传文件                    

 

后台接收文件的程序可以是任何语言(C#,PHP,Python 等)编写的,上述例子使用C#

很简单,无需为这个进度条做任何改动。

 

var flist = Request.Files;            for (int i = 0; i < flist.Count; i++)            {                string FilePath = "E:\\hooyes\\Files\\";                var c = flist[i];                FilePath = Path.Combine(FilePath, c.FileName);                c.SaveAs(FilePath);            }

以上引用自:

########################################################################

使用FormData对象

利用对象,你可以使用一系列的键值对来模拟一个完整的表单,然后使用XMLHttpRequest发送这个"表单".

创建一个FormData对象

你可以先创建一个空的FormData对象,然后使用方法向该对象里添加字段,如下:

var oMyForm = new FormData(); oMyForm.append("username", "Groucho"); oMyForm.append("accountnum", 123456); // 数字123456被立即转换成字符串"123456" // fileInputElement中已经包含了用户所选择的文件 oMyForm.append("userfile", fileInputElement.files[0]); var oFileBody = 'hey!'; // Blob对象包含的文件内容 var oBlob = new Blob([oFileBody], { type: "text/xml"}); oMyForm.append("webmasterfile", oBlob); var oReq = new XMLHttpRequest(); oReq.open("POST", "http://foo.com/submitform.php"); oReq.send(oMyForm);

注: 字段"userfile"和"webmasterfile"的值都包含了一个文件.通过 方法赋给字段"accountnum"的数字被自动转换为字符(字段的值可以是一个对象,一个对象,或者一个字符串,剩下其他类型的值都会被自动转换成字符串).

在该例子中,我们创建了一个名为oMyForm的FormData对象,该对象中包含了名为"username", "accountnum", "userfile" 以及 "webmasterfile"的字段名,然后使用XMLHttpRequest的方法把这些数据发送了出去."webmasterfile"字段的值不是一个字符串,还是一个对象.

使用HTML表单来初始化一个FormData对象

可以用一个已有的元素来初始化FormData对象,只需要把这个form元素作为参数传入FormData构造函数即可:

var newFormData = new FormData(someFormElement);

例如:

var formElement = document.getElementById("myFormElement"); var oReq = new XMLHttpRequest(); oReq.open("POST", "submitform.php"); oReq.send(new FormData(formElement));

你还可以在已有表单数据的基础上,继续添加新的键值对,如下:

var formElement = document.getElementById("myFormElement"); formData = new FormData(formElement); formData.append("serialnumber", serialNumber++); oReq.send(formData);

你可以通过这种方式添加一些不想让用户编辑的固定字段,然后再发送.

使用FormData对象发送文件

你还可以使用FormData来发送二进制文件.首先在HTML中要有一个包含了文件输入框的form元素:

Stash the file!

然后你就可以使用下面的代码来异步的上传用户所选择的文件:

function sendForm() {     var oOutput = document.getElementById("output");     var oData = new FormData(document.forms.namedItem("fileinfo"));     oData.append("CustomField", "This is some extra data");     var oReq = new XMLHttpRequest(); oReq.open("POST", "stash.php", true);     oReq.onload = function(oEvent) {         if (oReq.status == 200) {             oOutput.innerHTML = "Uploaded!";         } else {             oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.
"; } }; oReq.send(oData); }

你还可以不借助HTML表单,直接向对象中添加一个对象或者一个对象:

data.append("myfile", myBlob);

如果FormData对象中的某个字段值是一个对象,则在发送http请求时,代表该Blob对象所包含文件的文件名的"Content-Disposition"请求头的值在不同的浏览器下有所不同,Firefox使用了固定的字符串"blob,"而Chrome使用了一个随机字符串.

你还可以使用jQuery来发送FormData,但必须要正确的设置相关选项:

var fd = new FormData(document.getElementById("fileinfo")); fd.append("CustomField", "This is some extra data"); $.ajax({     url: "stash.php",     type: "POST",     data: fd,     processData: false,// 告诉jQuery不要去处理发送的数据     contentType: false // 告诉jQuery不要去设置Content-Type请求头 });

以上引用MDA,地址:

#########################################################################

通过传统的form表单提交的方式上传文件:

Html代码

测试通过Rest接口上传文件

指定文件名:

上传文件:

关键字1:

关键字2:

关键字3:

 

 

不过传统的form表单提交会导致页面刷新,但是在有些情况下,我们不希望页面被刷新,这种时候我们都是使用Ajax的方式进行请求的:

 

$.ajax({      url : "http://localhost:8080/STS/rest/user",      type : "POST",      data : $( '#postForm').serialize(),      success : function(data) {          $( '#serverResponse').html(data);      },      error : function(data) {          $( '#serverResponse').html(data.status + " : " + data.statusText + " : " + data.responseText);      }  });

 

如上,通过$('#postForm').serialize()可以对form表单进行序列化,从而将form表单中的所有参数传递到服务端。

 

但是上述方式,只能传递一般的参数,上传文件的文件流是无法被序列化并传递的。

不过如今主流浏览器都开始支持一个叫做FormData的对象,有了这个FormData,我们就可以轻松地使用Ajax方式进行文件上传了。

 

 

关于FormData及其用法


FormData是什么呢?我们来看看Mozilla上的介绍。

XMLHttpRequest Level 2添加了一个新的接口FormData.利用FormData对象,我们可以通过JavaScript用一些键值对来模拟一系列表单控件,我们还可以使用XMLHttpRequest的方法来异步的提交这个"表单".比起普通的ajax,使用FormData的最大优点就是我们可以异步上传一个二进制文件. 

 

所有主流浏览器的较新版本都已经支持这个对象了,比如Chrome 7+、Firefox 4+、IE 10+、Opera 12+、Safari 5+。

 

参见:

 

 

这里只展示一个通过from表单来初始化FormData的方式

<form enctype="multipart/form-data" method="post" name="fileinfo">

Js代码

 

var oData = new FormData(document.forms.namedItem("fileinfo" ));  oData.append( "CustomField", "This is some extra data" );  var oReq = new XMLHttpRequest();  oReq.open( "POST", "stash.php" , true );  oReq.onload = function(oEvent) {      if (oReq.status == 200) {          oOutput.innerHTML = "Uploaded!" ;    } else {          oOutput.innerHTML = "Error " + oReq.status + " occurred uploading your file.
"; } }; oReq.send(oData);

 

参见:

 

 

使用FormData,进行Ajax请求并上传文件


这里使用JQuery,但是老版本的JQuery比如1.2是不支持的,最好使用2.0或更新版本:

 

指定文件名:

上传文件:

 

Js代码

function doUpload() {       var formData = new FormData($( "#uploadForm" )[0]);       $.ajax({            url: 'http://localhost:8080/cfJAX_RS/rest/file/upload' ,            type: 'POST',            data: formData,            async: false,            cache: false,            contentType: false,            processData: false,            success: function (returndata) {                alert(returndata);            },            error: function (returndata) {                alert(returndata);            }       });  }

以上引用自:

转载于:https://my.oschina.net/yangting880815/blog/693309

你可能感兴趣的文章
POJ2125 Destroying The Graph
查看>>
详细的App推广前的准备工作
查看>>
15年1月的每天小程序
查看>>
多选插件multiselect.js
查看>>
Mysql基本用法-存储引擎-04
查看>>
使用GregorianCalendar模拟实现查看当前月的日历
查看>>
linux下的视频音频播放器终极解决方案
查看>>
让程序跨进网络时代——使用C语言获取百度源代码
查看>>
egret 精简游戏项目
查看>>
第 1 章 虚拟化 - 009 - KVM 网络虚拟化基础
查看>>
OpenJDK 源代码阅读之 BitSet
查看>>
观察者模式
查看>>
写给产品经理的技术书:客户端、服务端和交互相关技术
查看>>
Here's to the crazy ones.
查看>>
react router browserhistory 关于 Nginx配置
查看>>
Focal Loss 的前向与后向公式推导
查看>>
CSharp设计模式读书笔记(4):单例模式(学习难度:★☆☆☆☆,使用频率:★★★★☆)...
查看>>
PostgreSQL远端访问
查看>>
家庭里如何搭建一个互联网可访问的服务器
查看>>
eclipse与SVN 结合(删除SVN中已经上传的问题)
查看>>